diff --git a/.gitignore b/.gitignore
index 6993c75..feba811 100644
--- a/.gitignore
+++ b/.gitignore
@@ -101,9 +101,7 @@ logs/
# Frontend (Vite + React)
frontend/node_modules/
frontend/node/
-src/main/resources/static/assets/
-src/main/resources/static/index.html
-src/main/resources/static/vite.svg
+src/main/resources/static/
# Claude Code (개인 파일만 무시, 팀 파일은 추적)
.claude/settings.local.json
diff --git a/docs/RELEASE-NOTES.md b/docs/RELEASE-NOTES.md
index d251e59..6817940 100644
--- a/docs/RELEASE-NOTES.md
+++ b/docs/RELEASE-NOTES.md
@@ -4,6 +4,38 @@
## [Unreleased]
+## [2026-03-31]
+
+### 추가
+- 프론트엔드 UI 개편 (#115)
+ - 메인 화면 3개 섹션 카드 (Collector/Bypass/Risk&Compliance)
+ - 섹션별 Navbar 분리
+ - 플랫폼명 S&P Data Platform 변경
+- Risk&Compliance 값 변경 이력 확인 페이지 개발 (#111)
+ - 선박 위험지표/선박 제재/회사 제재 변경 이력 조회
+ - 선박/회사 기본정보 및 현재 Risk&Compliance 상태 조회
+ - Risk narrative(이전값/이후값) 표시 (LATERAL JOIN)
+ - indicator column_name 매핑으로 다국어 필드명 지원
+ - 다국어 캐시 (KO/EN 동시 조회, 언어 토글 즉시 전환)
+ - 독립 페이지 분리 (/risk-compliance-history)
+ - 국가코드 ISO2 변환 → 국기 이모지 표시
+ - Compliance 탭 분리 (Sanctions/Port Calls/STS/Suspicious)
+- Risk&Compliance Screening Guide 페이지 생성 (#109)
+- favicon 변경 (#105)
+- BY PASS API 등록 프로세스 설계 및 개발 (#63)
+ - 화면에서 API 정보 입력 → Java 코드 자동 생성 (Controller, Service)
+ - 공통 베이스 클래스 (BaseBypassService, BaseBypassController)
+ - JSON 응답 RAW 패스스루 (JsonNode)
+ - 같은 도메인 다중 엔드포인트 지원
+ - Swagger GroupedOpenApi 그룹 분리 및 사용자 설정 반영
+ - SPA 새로고침 오류 수정
+
+### 변경
+- API 응답 처리 방식에 따른 패키지 분리 (jobs/batch, jobs/web) (#66)
+
+### 기타
+- Swagger 서버 목록에서 불필요한 내부 IP 및 MDA 프록시 주소 제거 (#110)
+
## [2026-03-25]
### 추가
diff --git a/docs/ddl/indicator_column_name_mapping.sql b/docs/ddl/indicator_column_name_mapping.sql
new file mode 100644
index 0000000..c6ebc4f
--- /dev/null
+++ b/docs/ddl/indicator_column_name_mapping.sql
@@ -0,0 +1,193 @@
+-- =============================================================================
+-- Risk & Compliance Indicator 테이블에 column_name 매핑
+-- 목적: flctn_col_nm (이력 테이블 변동컬럼명) → indicator 테이블 JOIN 가능하도록
+-- 참고: INSERT SQL의 field_key 기준으로 매핑 (risk_indicator.sql, compliance_indicator.sql)
+-- =============================================================================
+
+-- ※ column_name 컬럼이 이미 INSERT SQL에 NULL로 포함되어 있으므로
+-- ALTER TABLE은 column_name 컬럼이 없는 경우에만 실행
+-- ALTER TABLE std_snp_data.risk_indicator ADD COLUMN column_name varchar(100);
+-- ALTER TABLE std_snp_data.compliance_indicator ADD COLUMN column_name varchar(100);
+
+
+-- 1. UPDATE: Risk Indicator
+-- -----------------------------------------------------------------------------
+
+-- AIS
+UPDATE std_snp_data.risk_indicator SET column_name = 'ais_notrcv_elps_days' WHERE field_key = 'Time since last seen on AIS';
+UPDATE std_snp_data.risk_indicator SET column_name = 'ais_lwrnk_days' WHERE field_key = 'Days under AIS coverage (last 12 months)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'mmsi_anom_message' WHERE field_key = 'Anomalous AIS Messages from MMSI (last 12 months)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'ais_up_imo_desc' WHERE field_key = 'IMO number transmitted correctly in AIS';
+UPDATE std_snp_data.risk_indicator SET column_name = 'othr_ship_nm_voy_yn' WHERE field_key = 'Sailing under name transmitted on AIS';
+
+-- PORT_CALLS
+UPDATE std_snp_data.risk_indicator SET column_name = 'port_prtcll' WHERE field_key = 'Port calls (last 12 months)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'recent_sanction_prtcll' WHERE field_key = 'Most recent sanctioned port call';
+UPDATE std_snp_data.risk_indicator SET column_name = 'port_risk' WHERE field_key = 'Highest ECR risk port call (last 12 months)';
+
+-- ASSOCIATED_WITH_RUSSIA
+UPDATE std_snp_data.risk_indicator SET column_name = 'rss_ownr_reg' WHERE field_key = 'Russian registration or ownership since February 2022';
+UPDATE std_snp_data.risk_indicator SET column_name = 'rss_port_call' WHERE field_key = 'Russian port calls since February 2022';
+UPDATE std_snp_data.risk_indicator SET column_name = 'rss_sts' WHERE field_key = 'Russian tanker STS since December 2022';
+
+-- BEHAVIOURAL_RISK
+UPDATE std_snp_data.risk_indicator SET column_name = 'recent_dark_actv' WHERE field_key = 'Most recent suspicious behavior detected';
+UPDATE std_snp_data.risk_indicator SET column_name = 'sts_job' WHERE field_key = 'Ship-to-Ship operations (last 12 months)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'draft_chg' WHERE field_key = 'Draught changes (last 12 months)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'drift_chg' WHERE field_key = 'Drifting high seas (last 12 months)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'ilgl_fshr_viol' WHERE field_key = 'Illegal Unreported or Unregulated (IUU) Fishing Violation';
+
+-- SAFETY_SECURITY_AND_INSPECTIONS
+UPDATE std_snp_data.risk_indicator SET column_name = 'risk_event' WHERE field_key = 'Casualty & risk events (last 3 years)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'fltsfty' WHERE field_key = 'Fleet casualty & risk (last 3 years)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'vslage' WHERE field_key = 'Age of ship (compared to peer group average)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'psc_inspection' WHERE field_key = 'Inspection (last 3 years)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'psc_inspection_elps_hr' WHERE field_key = 'Time since last inspection';
+UPDATE std_snp_data.risk_indicator SET column_name = 'psc_defect' WHERE field_key = 'PSC defects (last 3 years)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'psc_detained' WHERE field_key = 'PSC detentions (last 3 years)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'now_smgrc_evdc' WHERE field_key = 'Current Safety Management Certificate inspected';
+UPDATE std_snp_data.risk_indicator SET column_name = 'flt_psc' WHERE field_key = 'Fleet PSC detentions (last 3 years)';
+
+-- FLAG_RISK
+UPDATE std_snp_data.risk_indicator SET column_name = 'ntnlty_chg' WHERE field_key = 'Flag changes (last 3 years)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'ntnlty_prs_mou_perf' WHERE field_key = 'Flag Paris MOU performance';
+UPDATE std_snp_data.risk_indicator SET column_name = 'ntnlty_tky_mou_perf' WHERE field_key = 'Flag Tokyo MOU performance';
+UPDATE std_snp_data.risk_indicator SET column_name = 'ntnlty_uscg_mou_perf' WHERE field_key = 'Flag US Coastguard MOU performance';
+UPDATE std_snp_data.risk_indicator SET column_name = 'uscg_excl_ship_cert' WHERE field_key = 'Flag US Coastguard Qualship 21';
+UPDATE std_snp_data.risk_indicator SET column_name = 'risk_data_maint' WHERE field_key = 'Risk Data Maintained For Vessel';
+
+-- OWNER_AND_CLASSIFICATION
+UPDATE std_snp_data.risk_indicator SET column_name = 'now_clfic' WHERE field_key = 'Classification Society';
+UPDATE std_snp_data.risk_indicator SET column_name = 'clfic_status_chg' WHERE field_key = 'Class status changes (last 3 years)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'spc_inspection_ovdue' WHERE field_key = 'Special survey overdue';
+UPDATE std_snp_data.risk_indicator SET column_name = 'pni_insrnc' WHERE field_key = 'P&I club check';
+UPDATE std_snp_data.risk_indicator SET column_name = 'ship_nm_chg' WHERE field_key = 'Name changes (last 3 years)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'docc_chg' WHERE field_key = 'DOC company changes (last 3 years)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'gbo_chg' WHERE field_key = 'Group owner changes (last 3 years)';
+UPDATE std_snp_data.risk_indicator SET column_name = 'ownr_unk' WHERE field_key = 'Ownership unknown';
+UPDATE std_snp_data.risk_indicator SET column_name = 'sngl_ship_voy' WHERE field_key = 'Single-ship fleet (technical manager)';
+
+
+-- 2. UPDATE: Compliance Indicator - SHIP
+-- -----------------------------------------------------------------------------
+-- ※ DB 컬럼이 없는 지표 (Suspicious Behavior, Ownership Screening 등)는 매핑하지 않음
+
+-- Sanctions - Ship (US OFAC)
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ofac_sanction_list' WHERE field_key = 'Ship on OFAC Sanctions List (SDN)' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ofac_non_sdn_sanction_list' WHERE field_key = 'Ship on OFAC Consolidated (Non-SDN) List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ofac_cutn_list' WHERE field_key = 'Ship on OFAC Advisory List' AND indicator_type = 'SHIP';
+
+-- Sanctions - Ownership (US OFAC)
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_ofac_sanction_list' WHERE field_key = 'Ownership on OFAC Sanctions List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_ofcs_sanction_list' WHERE field_key = 'Ownership on OFAC SSI List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_ofac_sanction_country' WHERE field_key = 'Ownership in OFAC Sanctioned Country' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_ofac_sanction_hstry' WHERE field_key = 'Historical Ownership in OFAC Sanctioned Country' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_prnt_company_ofac_sanction_country' WHERE field_key = 'Parent Company in OFAC Sanctioned Country' AND indicator_type = 'SHIP';
+
+-- Sanctions - Ship (Non-US)
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_un_sanction_list' WHERE field_key = 'Ship on UN Security Council Sanctions List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_eu_sanction_list' WHERE field_key = 'Ship on EU Commission Sanctions List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_swi_sanction_list' WHERE field_key = 'Ship on Swiss SECO Sanctions List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_bes_sanction_list' WHERE field_key = 'Ship on HM Treasury (BES) Sanctions List' AND indicator_type = 'SHIP';
+
+-- Sanctions - Ownership (Non-US)
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_un_sanction_list' WHERE field_key = 'Ownership on UN Security Council Sanctions List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_eu_sanction_list' WHERE field_key = 'Ownership on EU Commission Sanctions List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_swi_sanction_list' WHERE field_key = 'Ownership on Swiss SECO Sanctions List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_bes_sanction_list' WHERE field_key = 'Ownership on HM Treasury (BES) Sanctions List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_can_sanction_list' WHERE field_key = 'Ownership on Government of Canada Sanctions List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_aus_sanction_list' WHERE field_key = 'Ownership on Australian DFAT Sanctions List' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_uae_sanction_list' WHERE field_key = 'Ownership on UAE Sanctions List' AND indicator_type = 'SHIP';
+
+-- Sanctions - FATF
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_fatf_rgl_zone' WHERE field_key = 'Ownership in FATF High-risk or Non-cooperative Jurisdiction' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_prnt_company_fatf_rgl_zone' WHERE field_key = 'Parent Company in FATF High-risk or Non-cooperative Jurisdiction' AND indicator_type = 'SHIP';
+
+-- Sanctions - Other
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_ownr_prnt_company_ncmplnc' WHERE field_key = 'Parent Company Noncompliant' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_flg_sanction_country' WHERE field_key = 'Flag Country Sanctioned' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_flg_sanction_country_hstry' WHERE field_key = 'Historical Flag Country Sanctioned' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_scrty_lgl_dspt_event' WHERE field_key = 'Security and Legal Dispute Event (Last 3 Years)' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_flg_dspt' WHERE field_key = 'Flag (MMSI, Call Sign) False or Flag Unknown' AND indicator_type = 'SHIP';
+
+-- Port Calls
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_sanction_country_prtcll_last_thr_m' WHERE field_key = 'Port Call Last 3 Months to Sanctioned Country' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_sanction_country_prtcll_last_six_m' WHERE field_key = 'Port Call Last 180 Days to Sanctioned Country' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_sanction_country_prtcll_last_twelve_m' WHERE field_key = 'Port Call Last 12 Months to Sanctioned Country' AND indicator_type = 'SHIP';
+
+-- STS Activity
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_sts_prtnr_non_compliance_twelve_m' WHERE field_key = 'STS Activity – Partner Ship Compliance Status' AND indicator_type = 'SHIP';
+
+-- Suspicious Behavior
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_dark_actv_ind' WHERE field_key = 'Dark for Extended Period in Watched Area (Severe)' AND indicator_type = 'SHIP';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'ship_dtld_info_ntmntd' WHERE field_key = 'Not Seen 7 Days Near Sanctioned/Sensitive Country' AND indicator_type = 'SHIP';
+
+-- Compliance Screening History
+UPDATE std_snp_data.compliance_indicator SET column_name = 'lgl_snths_sanction' WHERE field_key = 'Overall Compliance Change History' AND indicator_type = 'SHIP';
+
+
+-- 3. UPDATE: Compliance Indicator - COMPANY
+-- -----------------------------------------------------------------------------
+
+-- US Treasury Sanctions
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_ofac_sanction_list' WHERE field_key = 'Company on OFAC Entity List' AND indicator_type = 'COMPANY';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_ofac_non_sdn_sanction_list' WHERE field_key = 'Company on OFAC Non-SDN Entity List' AND indicator_type = 'COMPANY';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_ofacssi_sanction_list' WHERE field_key = 'Company on OFAC SSI Entity List' AND indicator_type = 'COMPANY';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_ofac_sanction_country' WHERE field_key = 'Company in US Treasury OFAC Sanctioned Country' AND indicator_type = 'COMPANY';
+
+-- Non-US Sanctions
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_un_sanction_list' WHERE field_key = 'Company on UN Security Council Entity List' AND indicator_type = 'COMPANY';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_eu_sanction_list' WHERE field_key = 'Company on EU Entity List' AND indicator_type = 'COMPANY';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_bes_sanction_list' WHERE field_key = 'Company on HM Treasury (BES) Entity List' AND indicator_type = 'COMPANY';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_can_sanction_list' WHERE field_key = 'Company on Canadian Entity List' AND indicator_type = 'COMPANY';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_aus_sanction_list' WHERE field_key = 'Company on Australian DFAT Entity List' AND indicator_type = 'COMPANY';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_uae_sanction_list' WHERE field_key = 'Company on UAE Entity List' AND indicator_type = 'COMPANY';
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_swiss_sanction_list' WHERE field_key = 'Company on Swiss SECO Entity List' AND indicator_type = 'COMPANY';
+
+-- FATF Jurisdiction
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_fatf_cmptnc_country' WHERE field_key = 'Company in FATF High-risk & Non-cooperative Jurisdiction' AND indicator_type = 'COMPANY';
+
+-- Parent Company
+UPDATE std_snp_data.compliance_indicator SET column_name = 'prnt_company_compliance_risk' WHERE field_key = 'Parent Company Compliance Risk' AND indicator_type = 'COMPANY';
+
+-- Compliance Screening Change History
+UPDATE std_snp_data.compliance_indicator SET column_name = 'company_snths_compliance_status' WHERE field_key = 'Historical Compliance Change Date (Company)' AND indicator_type = 'COMPANY';
+
+
+-- 4. 검증 쿼리
+-- -----------------------------------------------------------------------------
+
+-- 매핑된 항목 수 확인
+SELECT 'risk_indicator' as table_name,
+ COUNT(*) as total,
+ COUNT(column_name) as mapped,
+ COUNT(*) - COUNT(column_name) as unmapped
+FROM std_snp_data.risk_indicator
+UNION ALL
+SELECT 'compliance_indicator (SHIP)',
+ COUNT(*), COUNT(column_name), COUNT(*) - COUNT(column_name)
+FROM std_snp_data.compliance_indicator WHERE indicator_type = 'SHIP'
+UNION ALL
+SELECT 'compliance_indicator (COMPANY)',
+ COUNT(*), COUNT(column_name), COUNT(*) - COUNT(column_name)
+FROM std_snp_data.compliance_indicator WHERE indicator_type = 'COMPANY';
+
+-- 매핑 안 된 항목 확인 (DB 컬럼 없는 지표 = 정상적으로 NULL)
+SELECT indicator_id, field_key, column_name
+FROM std_snp_data.risk_indicator WHERE column_name IS NULL;
+
+SELECT indicator_id, field_key, indicator_type, column_name
+FROM std_snp_data.compliance_indicator WHERE column_name IS NULL;
+
+-- 전체 매핑 확인 (다국어 포함)
+SELECT ri.indicator_id, ri.field_key, ri.column_name, ril.field_name
+FROM std_snp_data.risk_indicator ri
+LEFT JOIN std_snp_data.risk_indicator_lang ril
+ ON ri.indicator_id = ril.indicator_id AND ril.lang_code = 'KO'
+ORDER BY ri.indicator_id;
+
+SELECT ci.indicator_id, ci.field_key, ci.indicator_type, ci.column_name, cil.field_name
+FROM std_snp_data.compliance_indicator ci
+LEFT JOIN std_snp_data.compliance_indicator_lang cil
+ ON ci.indicator_id = cil.indicator_id AND cil.lang_code = 'KO'
+ORDER BY ci.indicator_type, ci.indicator_id;
diff --git a/frontend/index.html b/frontend/index.html
index d8729c6..4958206 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -2,9 +2,13 @@
-
+
+
+
+
+
- S&P 배치 관리
+ S&P Data Platform
diff --git a/frontend/public/android-chrome-192x192.png b/frontend/public/android-chrome-192x192.png
new file mode 100644
index 0000000..5717dba
Binary files /dev/null and b/frontend/public/android-chrome-192x192.png differ
diff --git a/frontend/public/android-chrome-512x512.png b/frontend/public/android-chrome-512x512.png
new file mode 100644
index 0000000..99b3cda
Binary files /dev/null and b/frontend/public/android-chrome-512x512.png differ
diff --git a/frontend/public/apple-touch-icon.png b/frontend/public/apple-touch-icon.png
new file mode 100644
index 0000000..951b6fe
Binary files /dev/null and b/frontend/public/apple-touch-icon.png differ
diff --git a/frontend/public/favicon-16x16.png b/frontend/public/favicon-16x16.png
new file mode 100644
index 0000000..979ba88
Binary files /dev/null and b/frontend/public/favicon-16x16.png differ
diff --git a/frontend/public/favicon-32x32.png b/frontend/public/favicon-32x32.png
new file mode 100644
index 0000000..9e29032
Binary files /dev/null and b/frontend/public/favicon-32x32.png differ
diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico
new file mode 100644
index 0000000..13ffac1
Binary files /dev/null and b/frontend/public/favicon.ico differ
diff --git a/frontend/public/site.webmanifest b/frontend/public/site.webmanifest
new file mode 100644
index 0000000..6c7b599
--- /dev/null
+++ b/frontend/public/site.webmanifest
@@ -0,0 +1 @@
+{"name":"S&P 배치 관리","short_name":"S&P Batch","icons":[{"src":"/snp-api/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/snp-api/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
\ No newline at end of file
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index fa9d191..96c6356 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,11 +1,12 @@
import { lazy, Suspense } from 'react';
-import { BrowserRouter, Routes, Route } from 'react-router-dom';
+import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom';
import { ToastProvider, useToastContext } from './contexts/ToastContext';
import { ThemeProvider } from './contexts/ThemeContext';
import Navbar from './components/Navbar';
import ToastContainer from './components/Toast';
import LoadingSpinner from './components/LoadingSpinner';
+const MainMenu = lazy(() => import('./pages/MainMenu'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Jobs = lazy(() => import('./pages/Jobs'));
const Executions = lazy(() => import('./pages/Executions'));
@@ -14,17 +15,23 @@ const Recollects = lazy(() => import('./pages/Recollects'));
const RecollectDetail = lazy(() => import('./pages/RecollectDetail'));
const Schedules = lazy(() => import('./pages/Schedules'));
const Timeline = lazy(() => import('./pages/Timeline'));
+const BypassConfig = lazy(() => import('./pages/BypassConfig'));
+const ScreeningGuide = lazy(() => import('./pages/ScreeningGuide'));
+const RiskComplianceHistory = lazy(() => import('./pages/RiskComplianceHistory'));
function AppLayout() {
const { toasts, removeToast } = useToastContext();
+ const location = useLocation();
+ const isMainMenu = location.pathname === '/';
return (
-
+
}>
- } />
+ } />
+ } />
} />
} />
} />
@@ -32,6 +39,9 @@ function AppLayout() {
} />
} />
} />
+ } />
+ } />
+ } />
diff --git a/frontend/src/api/bypassApi.ts b/frontend/src/api/bypassApi.ts
new file mode 100644
index 0000000..abdcab7
--- /dev/null
+++ b/frontend/src/api/bypassApi.ts
@@ -0,0 +1,109 @@
+// API 응답 타입
+interface ApiResponse
{
+ success: boolean;
+ message: string;
+ data: T;
+ errorCode?: string;
+}
+
+// 타입 정의
+export interface BypassParamDto {
+ id?: number;
+ paramName: string;
+ paramType: string; // STRING, INTEGER, LONG, BOOLEAN
+ paramIn: string; // PATH, QUERY, BODY
+ required: boolean;
+ description: string;
+ example: string; // Swagger @Parameter example 값
+ sortOrder: number;
+}
+
+export interface BypassConfigRequest {
+ domainName: string;
+ displayName: string;
+ webclientBean: string;
+ externalPath: string;
+ httpMethod: string;
+ description: string;
+ params: BypassParamDto[];
+}
+
+export interface BypassConfigResponse {
+ id: number;
+ domainName: string;
+ endpointName: string;
+ displayName: string;
+ webclientBean: string;
+ externalPath: string;
+ httpMethod: string;
+ description: string;
+ generated: boolean;
+ generatedAt: string | null;
+ createdAt: string;
+ updatedAt: string;
+ params: BypassParamDto[];
+}
+
+export interface CodeGenerationResult {
+ controllerPath: string;
+ servicePaths: string[];
+ message: string;
+}
+
+export interface WebClientBeanInfo {
+ name: string;
+ description: string;
+}
+
+// BASE URL
+const BASE = '/snp-api/api/bypass-config';
+
+// 헬퍼 함수 (batchApi.ts 패턴과 동일)
+async function fetchJson(url: string): Promise {
+ const res = await fetch(url);
+ if (!res.ok) throw new Error(`API Error: ${res.status} ${res.statusText}`);
+ return res.json();
+}
+
+async function postJson(url: string, body?: unknown): Promise {
+ const res = await fetch(url, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: body != null ? JSON.stringify(body) : undefined,
+ });
+ if (!res.ok) throw new Error(`API Error: ${res.status} ${res.statusText}`);
+ return res.json();
+}
+
+async function putJson(url: string, body?: unknown): Promise {
+ const res = await fetch(url, {
+ method: 'PUT',
+ headers: { 'Content-Type': 'application/json' },
+ body: body != null ? JSON.stringify(body) : undefined,
+ });
+ if (!res.ok) throw new Error(`API Error: ${res.status} ${res.statusText}`);
+ return res.json();
+}
+
+async function deleteJson(url: string): Promise {
+ const res = await fetch(url, { method: 'DELETE' });
+ if (!res.ok) throw new Error(`API Error: ${res.status} ${res.statusText}`);
+ return res.json();
+}
+
+export const bypassApi = {
+ getConfigs: () =>
+ fetchJson>(BASE),
+ getConfig: (id: number) =>
+ fetchJson>(`${BASE}/${id}`),
+ createConfig: (data: BypassConfigRequest) =>
+ postJson>(BASE, data),
+ updateConfig: (id: number, data: BypassConfigRequest) =>
+ putJson>(`${BASE}/${id}`, data),
+ deleteConfig: (id: number) =>
+ deleteJson>(`${BASE}/${id}`),
+ generateCode: (id: number, force = false) =>
+ postJson>(`${BASE}/${id}/generate?force=${force}`),
+ getWebclientBeans: () =>
+ fetchJson>(`${BASE}/webclient-beans`),
+};
diff --git a/frontend/src/api/screeningGuideApi.ts b/frontend/src/api/screeningGuideApi.ts
new file mode 100644
index 0000000..4be75d1
--- /dev/null
+++ b/frontend/src/api/screeningGuideApi.ts
@@ -0,0 +1,148 @@
+// API 응답 타입
+interface ApiResponse {
+ success: boolean;
+ message: string;
+ data: T;
+}
+
+// Risk 지표 타입
+export interface RiskIndicatorResponse {
+ indicatorId: number;
+ fieldKey: string;
+ fieldName: string;
+ description: string;
+ conditionRed: string;
+ conditionAmber: string;
+ conditionGreen: string;
+ dataType: string;
+ collectionNote: string;
+}
+
+export interface RiskCategoryResponse {
+ categoryCode: string;
+ categoryName: string;
+ indicators: RiskIndicatorResponse[];
+}
+
+// Compliance 지표 타입
+export interface ComplianceIndicatorResponse {
+ indicatorId: number;
+ fieldKey: string;
+ fieldName: string;
+ description: string;
+ conditionRed: string;
+ conditionAmber: string;
+ conditionGreen: string;
+ dataType: string;
+ collectionNote: string;
+}
+
+export interface ComplianceCategoryResponse {
+ category: string;
+ indicatorType: string;
+ indicators: ComplianceIndicatorResponse[];
+}
+
+// 방법론 변경 이력 타입
+export interface MethodologyHistoryResponse {
+ historyId: number;
+ changeDate: string;
+ changeType: string;
+ updateTitle: string;
+ description: string;
+ collectionNote: string;
+}
+
+// 값 변경 이력 타입
+export interface ChangeHistoryResponse {
+ rowIndex: number;
+ searchKey: string;
+ lastModifiedDate: string;
+ changedColumnName: string;
+ beforeValue: string;
+ afterValue: string;
+ fieldName: string;
+ narrative: string;
+ prevNarrative: string;
+ sortOrder: number;
+}
+
+// 선박 기본 정보
+export interface ShipInfoResponse {
+ imoNo: string;
+ shipName: string;
+ shipStatus: string;
+ nationalityCode: string;
+ nationalityIsoCode: string | null;
+ nationality: string;
+ shipType: string;
+ dwt: string;
+ gt: string;
+ buildYear: string;
+ mmsiNo: string;
+ callSign: string;
+ shipTypeGroup: string;
+}
+
+// 회사 기본 정보
+export interface CompanyInfoResponse {
+ companyCode: string;
+ fullName: string;
+ abbreviation: string;
+ status: string;
+ parentCompanyCode: string | null;
+ parentCompanyName: string | null;
+ registrationCountry: string;
+ registrationCountryCode: string;
+ registrationCountryIsoCode: string | null;
+ controlCountry: string | null;
+ controlCountryCode: string | null;
+ controlCountryIsoCode: string | null;
+ foundedDate: string | null;
+ email: string | null;
+ phone: string | null;
+ website: string | null;
+}
+
+// 지표 현재 상태
+export interface IndicatorStatusResponse {
+ columnName: string;
+ fieldName: string;
+ category: string;
+ value: string | null;
+ narrative: string | null;
+ sortOrder: number;
+}
+
+const BASE = '/snp-api/api/screening-guide';
+
+async function fetchJson(url: string): Promise {
+ const res = await fetch(url);
+ if (!res.ok) throw new Error(`API Error: ${res.status}`);
+ return res.json();
+}
+
+export const screeningGuideApi = {
+ getRiskIndicators: (lang = 'KO') =>
+ fetchJson>(`${BASE}/risk-indicators?lang=${lang}`),
+ getComplianceIndicators: (lang = 'KO', type = 'SHIP') =>
+ fetchJson>(`${BASE}/compliance-indicators?lang=${lang}&type=${type}`),
+ getMethodologyHistory: (lang = 'KO') =>
+ fetchJson>(`${BASE}/methodology-history?lang=${lang}`),
+ getShipRiskHistory: (imoNo: string, lang = 'KO') =>
+ fetchJson>(`${BASE}/history/ship-risk?imoNo=${imoNo}&lang=${lang}`),
+ getShipComplianceHistory: (imoNo: string, lang = 'KO') =>
+ fetchJson>(`${BASE}/history/ship-compliance?imoNo=${imoNo}&lang=${lang}`),
+ getCompanyComplianceHistory: (companyCode: string, lang = 'KO') =>
+ fetchJson>(`${BASE}/history/company-compliance?companyCode=${companyCode}&lang=${lang}`),
+ getShipInfo: (imoNo: string) =>
+ fetchJson>(`${BASE}/ship-info?imoNo=${imoNo}`),
+ getShipRiskStatus: (imoNo: string, lang = 'KO') =>
+ fetchJson>(`${BASE}/ship-risk-status?imoNo=${imoNo}&lang=${lang}`),
+ getShipComplianceStatus: (imoNo: string, lang = 'KO') =>
+ fetchJson>(`${BASE}/ship-compliance-status?imoNo=${imoNo}&lang=${lang}`),
+ getCompanyInfo: (companyCode: string) =>
+ fetchJson>(`${BASE}/company-info?companyCode=${companyCode}`),
+ getCompanyComplianceStatus: (companyCode: string, lang = 'KO') =>
+ fetchJson>(`${BASE}/company-compliance-status?companyCode=${companyCode}&lang=${lang}`),
+};
diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx
index fa9be55..adf72d7 100644
--- a/frontend/src/components/Navbar.tsx
+++ b/frontend/src/components/Navbar.tsx
@@ -1,55 +1,107 @@
import { Link, useLocation } from 'react-router-dom';
import { useThemeContext } from '../contexts/ThemeContext';
-const navItems = [
- { path: '/', label: '대시보드', icon: '📊' },
- { path: '/executions', label: '실행 이력', icon: '📋' },
- { path: '/recollects', label: '재수집 이력', icon: '🔄' },
- { path: '/jobs', label: '작업', icon: '⚙️' },
- { path: '/schedules', label: '스케줄', icon: '🕐' },
- { path: '/schedule-timeline', label: '타임라인', icon: '📅' },
+interface NavSection {
+ key: string;
+ title: string;
+ paths: string[];
+ items: { path: string; label: string; icon: string }[];
+}
+
+const sections: NavSection[] = [
+ {
+ key: 'collector',
+ title: 'S&P Collector',
+ paths: ['/dashboard', '/jobs', '/executions', '/recollects', '/schedules', '/schedule-timeline'],
+ items: [
+ { path: '/dashboard', label: '대시보드', icon: '📊' },
+ { path: '/executions', label: '실행 이력', icon: '📋' },
+ { path: '/recollects', label: '재수집 이력', icon: '🔄' },
+ { path: '/jobs', label: '작업', icon: '⚙️' },
+ { path: '/schedules', label: '스케줄', icon: '🕐' },
+ { path: '/schedule-timeline', label: '타임라인', icon: '📅' },
+ ],
+ },
+ {
+ key: 'bypass',
+ title: 'S&P Bypass',
+ paths: ['/bypass-config'],
+ items: [
+ { path: '/bypass-config', label: 'Bypass API', icon: '🔗' },
+ ],
+ },
+ {
+ key: 'risk',
+ title: 'S&P Risk & Compliance',
+ paths: ['/screening-guide', '/risk-compliance-history'],
+ items: [
+ { path: '/screening-guide', label: 'Screening Guide', icon: '⚖️' },
+ { path: '/risk-compliance-history', label: 'Change History', icon: '📜' },
+ ],
+ },
];
-export default function Navbar() {
- const location = useLocation();
- const { theme, toggle } = useThemeContext();
-
- const isActive = (path: string) => {
- if (path === '/') return location.pathname === '/';
- return location.pathname.startsWith(path);
- };
-
- return (
-
-
-
- S&P 배치 관리
-
-
- {navItems.map((item) => (
-
- {item.icon}
- {item.label}
-
- ))}
-
- {theme === 'dark' ? '☀️' : '🌙'}
-
-
-
-
- );
+function getCurrentSection(pathname: string): NavSection | null {
+ for (const section of sections) {
+ if (section.paths.some((p) => pathname === p || pathname.startsWith(p + '/'))) {
+ return section;
+ }
+ }
+ return null;
+}
+
+export default function Navbar() {
+ const location = useLocation();
+ const { theme, toggle } = useThemeContext();
+ const currentSection = getCurrentSection(location.pathname);
+
+ // 메인 화면에서는 Navbar 숨김
+ if (!currentSection) return null;
+
+ const isActive = (path: string) => {
+ if (path === '/dashboard') return location.pathname === '/dashboard';
+ return location.pathname === path || location.pathname.startsWith(path + '/');
+ };
+
+ return (
+
+
+
+
+ ← 메인
+
+ |
+ {currentSection.title}
+
+
+ {currentSection.items.map((item) => (
+
+ {item.icon}
+ {item.label}
+
+ ))}
+
+ {theme === 'dark' ? '☀️' : '🌙'}
+
+
+
+
+ );
}
diff --git a/frontend/src/components/bypass/BypassConfigModal.tsx b/frontend/src/components/bypass/BypassConfigModal.tsx
new file mode 100644
index 0000000..6a3b854
--- /dev/null
+++ b/frontend/src/components/bypass/BypassConfigModal.tsx
@@ -0,0 +1,222 @@
+import { useState, useEffect } from 'react';
+import type {
+ BypassConfigRequest,
+ BypassConfigResponse,
+ BypassParamDto,
+ WebClientBeanInfo,
+} from '../../api/bypassApi';
+import BypassStepBasic from './BypassStepBasic';
+import BypassStepParams from './BypassStepParams';
+
+interface BypassConfigModalProps {
+ open: boolean;
+ editConfig: BypassConfigResponse | null;
+ webclientBeans: WebClientBeanInfo[];
+ onSave: (data: BypassConfigRequest) => Promise;
+ onClose: () => void;
+}
+
+type StepNumber = 1 | 2;
+
+const STEP_LABELS: Record = {
+ 1: '기본 정보',
+ 2: '파라미터',
+};
+
+const DEFAULT_FORM: Omit = {
+ domainName: '',
+ displayName: '',
+ webclientBean: '',
+ externalPath: '',
+ httpMethod: 'GET',
+ description: '',
+};
+
+export default function BypassConfigModal({
+ open,
+ editConfig,
+ webclientBeans,
+ onSave,
+ onClose,
+}: BypassConfigModalProps) {
+ const [step, setStep] = useState(1);
+ const [domainName, setDomainName] = useState('');
+ const [displayName, setDisplayName] = useState('');
+ const [webclientBean, setWebclientBean] = useState('');
+ const [externalPath, setExternalPath] = useState('');
+ const [httpMethod, setHttpMethod] = useState('GET');
+ const [description, setDescription] = useState('');
+ const [params, setParams] = useState([]);
+ const [saving, setSaving] = useState(false);
+
+ useEffect(() => {
+ if (!open) return;
+ setStep(1);
+ if (editConfig) {
+ setDomainName(editConfig.domainName);
+ setDisplayName(editConfig.displayName);
+ setWebclientBean(editConfig.webclientBean);
+ setExternalPath(editConfig.externalPath);
+ setHttpMethod(editConfig.httpMethod);
+ setDescription(editConfig.description);
+ setParams(editConfig.params);
+ } else {
+ setDomainName(DEFAULT_FORM.domainName);
+ setDisplayName(DEFAULT_FORM.displayName);
+ setWebclientBean(DEFAULT_FORM.webclientBean);
+ setExternalPath(DEFAULT_FORM.externalPath);
+ setHttpMethod(DEFAULT_FORM.httpMethod);
+ setDescription(DEFAULT_FORM.description);
+ setParams([]);
+ }
+ }, [open, editConfig]);
+
+ if (!open) return null;
+
+ const handleBasicChange = (field: string, value: string) => {
+ switch (field) {
+ case 'domainName': setDomainName(value); break;
+ case 'displayName': setDisplayName(value); break;
+ case 'webclientBean': setWebclientBean(value); break;
+ case 'externalPath': setExternalPath(value); break;
+ case 'httpMethod': setHttpMethod(value); break;
+ case 'description': setDescription(value); break;
+ }
+ };
+
+ const handleSave = async () => {
+ setSaving(true);
+ try {
+ await onSave({
+ domainName,
+ displayName,
+ webclientBean,
+ externalPath,
+ httpMethod,
+ description,
+ params,
+ });
+ onClose();
+ } finally {
+ setSaving(false);
+ }
+ };
+
+ const steps: StepNumber[] = [1, 2];
+
+ return (
+
+
e.stopPropagation()}
+ >
+ {/* 헤더 */}
+
+
+ {editConfig ? 'Bypass API 수정' : 'Bypass API 등록'}
+
+
+ {/* 스텝 인디케이터 */}
+
+ {steps.map((s, idx) => (
+
+
+ s
+ ? 'bg-wing-accent/30 text-wing-accent'
+ : 'bg-wing-card text-wing-muted border border-wing-border',
+ ].join(' ')}
+ >
+ {s}
+
+
+ {STEP_LABELS[s]}
+
+
+ {idx < steps.length - 1 && (
+
+ )}
+
+ ))}
+
+
+
+ {/* 본문 */}
+
+ {step === 1 && (
+
+ )}
+ {step === 2 && (
+
+ )}
+
+
+ {/* 하단 버튼 */}
+
+
+ {step > 1 && (
+ setStep((s) => (s - 1) as StepNumber)}
+ className="px-4 py-2 text-sm font-medium text-wing-text bg-wing-card rounded-lg hover:bg-wing-hover transition-colors"
+ >
+ ← 이전
+
+ )}
+
+
+ {step === 1 && (
+
+ 취소
+
+ )}
+ {step < 2 ? (
+ setStep((s) => (s + 1) as StepNumber)}
+ className="px-4 py-2 text-sm font-medium text-white bg-wing-accent hover:bg-wing-accent/80 rounded-lg transition-colors"
+ >
+ 다음 →
+
+ ) : (
+
+ {saving ? '저장 중...' : '저장'}
+
+ )}
+
+
+
+
+ );
+}
diff --git a/frontend/src/components/bypass/BypassStepBasic.tsx b/frontend/src/components/bypass/BypassStepBasic.tsx
new file mode 100644
index 0000000..5056b07
--- /dev/null
+++ b/frontend/src/components/bypass/BypassStepBasic.tsx
@@ -0,0 +1,142 @@
+import type { WebClientBeanInfo } from '../../api/bypassApi';
+
+interface BypassStepBasicProps {
+ domainName: string;
+ displayName: string;
+ webclientBean: string;
+ externalPath: string;
+ httpMethod: string;
+ description: string;
+ webclientBeans: WebClientBeanInfo[];
+ isEdit: boolean;
+ onChange: (field: string, value: string) => void;
+}
+
+export default function BypassStepBasic({
+ domainName,
+ displayName,
+ webclientBean,
+ externalPath,
+ httpMethod,
+ description,
+ webclientBeans,
+ isEdit,
+ onChange,
+}: BypassStepBasicProps) {
+ return (
+
+
+ BYPASS API의 기본 정보를 입력하세요. 도메인명을 기반으로 코드가 생성됩니다.
+
+
+
+ {/* 도메인명 */}
+
+
+ 도메인명 *
+
+
onChange('domainName', e.target.value)}
+ disabled={isEdit}
+ placeholder="예: riskByImo"
+ pattern="[a-zA-Z][a-zA-Z0-9]*"
+ className={[
+ 'w-full px-3 py-2 text-sm rounded-lg border',
+ 'border-wing-border bg-wing-card text-wing-text',
+ 'placeholder:text-wing-muted focus:outline-none focus:ring-2 focus:ring-wing-accent/50',
+ isEdit ? 'opacity-50 cursor-not-allowed' : '',
+ ].join(' ')}
+ />
+
영문 소문자/숫자 조합 (수정 불가)
+
+
+ {/* 표시명 */}
+
+
+ 표시명 *
+
+ onChange('displayName', e.target.value)}
+ placeholder="예: IMO 기반 리스크 조회"
+ className="w-full px-3 py-2 text-sm rounded-lg border border-wing-border bg-wing-card text-wing-text placeholder:text-wing-muted focus:outline-none focus:ring-2 focus:ring-wing-accent/50"
+ />
+
+
+ {/* WebClient */}
+
+
+ WebClient Bean *
+
+ onChange('webclientBean', e.target.value)}
+ className="w-full px-3 py-2 text-sm rounded-lg border border-wing-border bg-wing-card text-wing-text focus:outline-none focus:ring-2 focus:ring-wing-accent/50"
+ >
+ 선택하세요
+ {webclientBeans.map((bean) => (
+
+ {bean.description || bean.name}
+
+ ))}
+
+
+
+ {/* 외부 API 경로 */}
+
+
+ 외부 API 경로 *
+
+ onChange('externalPath', e.target.value)}
+ placeholder="/RiskAndCompliance/RisksByImos"
+ className="w-full px-3 py-2 text-sm rounded-lg border border-wing-border bg-wing-card text-wing-text placeholder:text-wing-muted focus:outline-none focus:ring-2 focus:ring-wing-accent/50"
+ />
+
+
+ {/* HTTP 메서드 */}
+
+
+ HTTP 메서드 *
+
+
+ {['GET', 'POST'].map((method) => (
+ onChange('httpMethod', method)}
+ className={[
+ 'flex-1 py-2 text-sm font-medium rounded-lg border transition-colors',
+ httpMethod === method
+ ? 'bg-wing-accent text-white border-wing-accent'
+ : 'bg-wing-card text-wing-muted border-wing-border hover:bg-wing-hover',
+ ].join(' ')}
+ >
+ {method}
+
+ ))}
+
+
+
+ {/* 설명 */}
+
+
+ 설명
+
+
+
+
+ );
+}
diff --git a/frontend/src/components/bypass/BypassStepParams.tsx b/frontend/src/components/bypass/BypassStepParams.tsx
new file mode 100644
index 0000000..cd767e1
--- /dev/null
+++ b/frontend/src/components/bypass/BypassStepParams.tsx
@@ -0,0 +1,157 @@
+import type { BypassParamDto } from '../../api/bypassApi';
+
+interface BypassStepParamsProps {
+ params: BypassParamDto[];
+ onChange: (params: BypassParamDto[]) => void;
+}
+
+const PARAM_TYPES = ['STRING', 'INTEGER', 'LONG', 'BOOLEAN'];
+const PARAM_IN_OPTIONS = ['PATH', 'QUERY', 'BODY'];
+
+function createEmptyParam(sortOrder: number): BypassParamDto {
+ return {
+ paramName: '',
+ paramType: 'STRING',
+ paramIn: 'QUERY',
+ required: false,
+ description: '',
+ example: '',
+ sortOrder,
+ };
+}
+
+export default function BypassStepParams({ params, onChange }: BypassStepParamsProps) {
+ const handleAdd = () => {
+ onChange([...params, createEmptyParam(params.length)]);
+ };
+
+ const handleDelete = (index: number) => {
+ const updated = params
+ .filter((_, i) => i !== index)
+ .map((p, i) => ({ ...p, sortOrder: i }));
+ onChange(updated);
+ };
+
+ const handleChange = (index: number, field: keyof BypassParamDto, value: string | boolean | number) => {
+ const updated = params.map((p, i) =>
+ i === index ? { ...p, [field]: value } : p,
+ );
+ onChange(updated);
+ };
+
+ return (
+
+
+ 외부 API 호출에 필요한 파라미터를 정의하세요.
+
+
+ {params.length === 0 ? (
+
+ 파라미터가 없습니다. 추가 버튼을 클릭하세요.
+
+ ) : (
+
+
+
+
+ 이름
+ 타입
+ 위치
+ 필수
+ 설명
+ Example
+
+
+
+
+ {params.map((param, index) => (
+
+
+ handleChange(index, 'paramName', e.target.value)}
+ placeholder="paramName"
+ className="w-full px-2 py-1.5 text-sm rounded border border-wing-border bg-wing-surface text-wing-text placeholder:text-wing-muted focus:outline-none focus:ring-1 focus:ring-wing-accent/50"
+ />
+
+
+ handleChange(index, 'paramType', e.target.value)}
+ className="w-full px-2 py-1.5 text-sm rounded border border-wing-border bg-wing-surface text-wing-text focus:outline-none focus:ring-1 focus:ring-wing-accent/50"
+ >
+ {PARAM_TYPES.map((t) => (
+ {t}
+ ))}
+
+
+
+ handleChange(index, 'paramIn', e.target.value)}
+ className="w-full px-2 py-1.5 text-sm rounded border border-wing-border bg-wing-surface text-wing-text focus:outline-none focus:ring-1 focus:ring-wing-accent/50"
+ >
+ {PARAM_IN_OPTIONS.map((o) => (
+ {o}
+ ))}
+
+
+
+ handleChange(index, 'required', e.target.checked)}
+ className="w-4 h-4 rounded border-wing-border text-wing-accent focus:ring-wing-accent/50 cursor-pointer"
+ />
+
+
+ handleChange(index, 'description', e.target.value)}
+ placeholder="파라미터 설명"
+ className="w-full px-2 py-1.5 text-sm rounded border border-wing-border bg-wing-surface text-wing-text placeholder:text-wing-muted focus:outline-none focus:ring-1 focus:ring-wing-accent/50"
+ />
+
+
+ handleChange(index, 'example', e.target.value)}
+ placeholder="예: 9876543"
+ className="w-full px-2 py-1.5 text-sm rounded border border-wing-border bg-wing-surface text-wing-text placeholder:text-wing-muted focus:outline-none focus:ring-1 focus:ring-wing-accent/50"
+ />
+
+
+ handleDelete(index)}
+ className="p-1.5 text-wing-muted hover:text-red-500 hover:bg-red-50 rounded transition-colors"
+ title="삭제"
+ >
+
+
+
+
+
+
+ ))}
+
+
+
+ )}
+
+
+
+
+
+ 파라미터 추가
+
+
+ );
+}
diff --git a/frontend/src/components/screening/ComplianceTab.tsx b/frontend/src/components/screening/ComplianceTab.tsx
new file mode 100644
index 0000000..a4e563e
--- /dev/null
+++ b/frontend/src/components/screening/ComplianceTab.tsx
@@ -0,0 +1,385 @@
+import { useState, useEffect } from 'react';
+import {
+ screeningGuideApi,
+ type ComplianceCategoryResponse,
+ type ComplianceIndicatorResponse,
+} from '../../api/screeningGuideApi';
+
+interface ComplianceTabProps {
+ lang: string;
+}
+
+type ViewMode = 'table' | 'card';
+type IndicatorType = 'SHIP' | 'COMPANY';
+
+const SHIP_CAT_COLORS: Record = {
+ 'Sanctions – Ship (US OFAC)': '#1e3a5f',
+ 'Sanctions – Ownership (US OFAC)': '#1d4ed8',
+ 'Sanctions – Ship (Non-US)': '#065f46',
+ 'Sanctions – Ownership (Non-US)': '#0f766e',
+ 'Sanctions – FATF': '#6b21a8',
+ 'Sanctions – Other': '#991b1b',
+ 'Port Calls': '#065f46',
+ 'STS Activity': '#0f766e',
+ 'Dark Activity': '#374151',
+};
+
+const COMPANY_CAT_COLORS: Record = {
+ 'Company Sanctions (US OFAC)': '#1e3a5f',
+ 'Company Sanctions (Non-US)': '#065f46',
+ 'Company Compliance': '#6b21a8',
+ 'Company Risk': '#92400e',
+};
+
+function getCatHex(categoryName: string, type: IndicatorType): string {
+ const map = type === 'SHIP' ? SHIP_CAT_COLORS : COMPANY_CAT_COLORS;
+ return map[categoryName] ?? '#374151';
+}
+
+interface FlatRow {
+ category: string;
+ indicatorType: string;
+ indicator: ComplianceIndicatorResponse;
+}
+
+export default function ComplianceTab({ lang }: ComplianceTabProps) {
+ const [categories, setCategories] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+ const [selectedCategory, setSelectedCategory] = useState('전체');
+ const [viewMode, setViewMode] = useState('table');
+ const [indicatorType, setIndicatorType] = useState('SHIP');
+
+ useEffect(() => {
+ setLoading(true);
+ setError(null);
+ setSelectedCategory('전체');
+ screeningGuideApi
+ .getComplianceIndicators(lang, indicatorType)
+ .then((res) => setCategories(res.data ?? []))
+ .catch((err: Error) => setError(err.message))
+ .finally(() => setLoading(false));
+ }, [lang, indicatorType]);
+
+ const flatRows: FlatRow[] = categories.flatMap((cat) =>
+ cat.indicators.map((ind) => ({
+ category: cat.category,
+ indicatorType: cat.indicatorType,
+ indicator: ind,
+ })),
+ );
+
+ const filtered: FlatRow[] =
+ selectedCategory === '전체'
+ ? flatRows
+ : flatRows.filter((r) => r.category === selectedCategory);
+
+ const uniqueCategories = Array.from(new Set(flatRows.map((r) => r.category)));
+
+ function downloadCSV() {
+ const bom = '\uFEFF';
+ const headers = [
+ '카테고리',
+ '타입',
+ '필드키',
+ '필드명',
+ '설명',
+ 'RED 조건',
+ 'AMBER 조건',
+ 'GREEN 조건',
+ '데이터 타입',
+ '이력 관리 참고사항',
+ ];
+ const rows = flatRows.map((r) =>
+ [
+ r.category,
+ r.indicatorType,
+ r.indicator.fieldKey,
+ r.indicator.fieldName,
+ r.indicator.description,
+ r.indicator.conditionRed,
+ r.indicator.conditionAmber,
+ r.indicator.conditionGreen,
+ r.indicator.dataType,
+ r.indicator.collectionNote,
+ ]
+ .map((v) => `"${(v ?? '').replace(/"/g, '""')}"`)
+ .join(','),
+ );
+ const csv = bom + [headers.join(','), ...rows].join('\n');
+ const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
+ const a = document.createElement('a');
+ a.href = URL.createObjectURL(blob);
+ a.download = `MIRS_Compliance_${indicatorType}.csv`;
+ a.click();
+ }
+
+ return (
+
+ {/* SHIP / COMPANY 토글 */}
+
+ setIndicatorType('SHIP')}
+ className={`px-5 py-2 rounded-lg text-sm font-bold transition-all border ${
+ indicatorType === 'SHIP'
+ ? 'bg-slate-900 text-white border-slate-900 shadow-md'
+ : 'bg-wing-card text-wing-muted border-wing-border hover:text-wing-text'
+ }`}
+ >
+ 선박 컴플라이언스 (SHIP)
+
+ setIndicatorType('COMPANY')}
+ className={`px-5 py-2 rounded-lg text-sm font-bold transition-all border ${
+ indicatorType === 'COMPANY'
+ ? 'bg-slate-900 text-white border-slate-900 shadow-md'
+ : 'bg-wing-card text-wing-muted border-wing-border hover:text-wing-text'
+ }`}
+ >
+ 기업 컴플라이언스 (COMPANY)
+
+
+
+ {loading && (
+
+ )}
+
+ {error && (
+
+ 데이터 로딩 실패: {error}
+
+ )}
+
+ {!loading && !error && (
+ <>
+ {/* 카테고리 요약 카드 */}
+
+ {uniqueCategories.map((catName) => {
+ const count = flatRows.filter((r) => r.category === catName).length;
+ const isActive = selectedCategory === catName;
+ const hex = getCatHex(catName, indicatorType);
+ return (
+
+ setSelectedCategory(isActive ? '전체' : catName)
+ }
+ className="rounded-lg p-3 text-center cursor-pointer transition-all border-2 text-left"
+ style={{
+ background: isActive ? hex : undefined,
+ borderColor: isActive ? hex : undefined,
+ }}
+ >
+
+ {count}
+
+
+ {catName}
+
+
+ );
+ })}
+
+
+ {/* 컨트롤 바 */}
+
+
setSelectedCategory('전체')}
+ className={`px-4 py-1.5 rounded-full text-xs font-bold transition-colors border ${
+ selectedCategory === '전체'
+ ? 'bg-slate-900 text-white border-slate-900'
+ : 'bg-wing-card text-wing-muted border-wing-border hover:text-wing-text'
+ }`}
+ >
+ 전체 ({flatRows.length})
+
+
+
+ 표시:{' '}
+ {filtered.length} 개 항목
+
+
setViewMode(viewMode === 'table' ? 'card' : 'table')}
+ className="px-3 py-1.5 rounded-lg border border-wing-border bg-wing-card text-wing-muted text-xs font-semibold hover:text-wing-text transition-colors"
+ >
+ {viewMode === 'table' ? '📋 카드 보기' : '📊 테이블 보기'}
+
+
+ ⬇ CSV 다운로드
+
+
+
+ {/* 테이블 뷰 */}
+ {viewMode === 'table' && (
+
+
+
+
+
+ {[
+ '카테고리',
+ '필드명',
+ '설명',
+ '🔴 RED',
+ '🟡 AMBER',
+ '🟢 GREEN',
+ '데이터 타입',
+ '이력 관리 참고',
+ ].map((h) => (
+
+ {h}
+
+ ))}
+
+
+
+ {filtered.map((row, i) => {
+ const showCat =
+ i === 0 ||
+ filtered[i - 1].category !== row.category;
+ const hex = getCatHex(row.category, indicatorType);
+ return (
+
+
+ {showCat && (
+
+ {row.category}
+
+ )}
+
+
+
+ {row.indicator.fieldName}
+
+
+ {row.indicator.fieldKey}
+
+
+
+ {row.indicator.description}
+
+
+
+ {row.indicator.conditionRed}
+
+
+
+
+ {row.indicator.conditionAmber}
+
+
+
+
+ {row.indicator.conditionGreen}
+
+
+
+ {row.indicator.dataType}
+
+
+ {row.indicator.collectionNote &&
+ `💡 ${row.indicator.collectionNote}`}
+
+
+ );
+ })}
+
+
+
+
+ )}
+
+ {/* 카드 뷰 */}
+ {viewMode === 'card' && (
+
+ {filtered.map((row, i) => {
+ const hex = getCatHex(row.category, indicatorType);
+ return (
+
+
+
+ {row.category}
+
+
+ {row.indicator.dataType}
+
+
+
+
+ {row.indicator.fieldName}
+
+
+ {row.indicator.fieldKey}
+
+
+ {row.indicator.description}
+
+
+
+
+ 🔴 RED
+
+
+ {row.indicator.conditionRed}
+
+
+
+
+ 🟡 AMBER
+
+
+ {row.indicator.conditionAmber}
+
+
+
+
+ 🟢 GREEN
+
+
+ {row.indicator.conditionGreen}
+
+
+
+ {row.indicator.collectionNote && (
+
+ 💡 {row.indicator.collectionNote}
+
+ )}
+
+
+ );
+ })}
+
+ )}
+ >
+ )}
+
+ );
+}
diff --git a/frontend/src/components/screening/HistoryTab.tsx b/frontend/src/components/screening/HistoryTab.tsx
new file mode 100644
index 0000000..0507406
--- /dev/null
+++ b/frontend/src/components/screening/HistoryTab.tsx
@@ -0,0 +1,908 @@
+import { useState, useMemo } from 'react';
+import { screeningGuideApi, type ChangeHistoryResponse, type ShipInfoResponse, type CompanyInfoResponse, type IndicatorStatusResponse } from '../../api/screeningGuideApi';
+
+type HistoryType = 'ship-risk' | 'ship-compliance' | 'company-compliance';
+
+interface HistoryTabProps {
+ lang: string;
+}
+
+const HISTORY_TYPES: {
+ key: HistoryType;
+ label: string;
+ searchLabel: string;
+ searchPlaceholder: string;
+ overallColumn: string | null;
+}[] = [
+ {
+ key: 'ship-risk',
+ label: '선박 위험지표',
+ searchLabel: 'IMO 번호',
+ searchPlaceholder: 'IMO 번호 : 9672533',
+ overallColumn: null,
+ },
+ {
+ key: 'ship-compliance',
+ label: '선박 제재',
+ searchLabel: 'IMO 번호',
+ searchPlaceholder: 'IMO 번호 : 9672533',
+ overallColumn: 'lgl_snths_sanction',
+ },
+ {
+ key: 'company-compliance',
+ label: '회사 제재',
+ searchLabel: '회사 코드',
+ searchPlaceholder: '회사 코드 : 1288896',
+ overallColumn: 'company_snths_compliance_status',
+ },
+];
+
+interface GroupedHistory {
+ lastModifiedDate: string;
+ items: ChangeHistoryResponse[];
+ overallBefore: string | null;
+ overallAfter: string | null;
+}
+
+const STATUS_MAP: Record = {
+ '0': { label: 'All Clear', className: 'bg-green-100 text-green-800 border-green-300' },
+ '1': { label: 'Warning', className: 'bg-yellow-100 text-yellow-800 border-yellow-300' },
+ '2': { label: 'Severe', className: 'bg-red-100 text-red-800 border-red-300' },
+};
+
+const STATUS_COLORS: Record = {
+ '0': '#22c55e',
+ '1': '#eab308',
+ '2': '#ef4444',
+};
+
+const STATUS_LABELS: Record = {
+ '0': 'All Clear',
+ '1': 'Warning',
+ '2': 'Severe',
+};
+
+function StatusBadge({ value }: { value: string | null }) {
+ if (value == null || value === '') return null;
+ const status = STATUS_MAP[value];
+ if (!status) return {value} ;
+ return (
+
+ {status.label}
+
+ );
+}
+
+function countryFlag(code: string | null | undefined): string {
+ if (!code || code.length < 2) return '';
+ const cc = code.slice(0, 2).toUpperCase();
+ const codePoints = [...cc].map((c) => 0x1F1E6 + c.charCodeAt(0) - 65);
+ return String.fromCodePoint(...codePoints);
+}
+
+function RiskValueCell({ value, narrative }: { value: string | null; narrative?: string }) {
+ if (value == null || value === '') return null;
+ const color = STATUS_COLORS[value] ?? '#6b7280';
+ const label = narrative || STATUS_LABELS[value] || value;
+ return (
+
+ ●
+ {label}
+
+ );
+}
+
+const COMPLIANCE_STATUS: Record = {
+ '0': { label: 'No', className: 'bg-green-100 text-green-800' },
+ '1': { label: 'Warning', className: 'bg-yellow-100 text-yellow-800' },
+ '2': { label: 'Yes', className: 'bg-red-100 text-red-800' },
+};
+
+function getRiskLabel(item: IndicatorStatusResponse): string {
+ // IUU Fishing: All Clear -> None recorded
+ if (item.columnName === 'ilgl_fshr_viol' && item.value === '0') return 'None recorded';
+ // Risk Data Maintained: 0 -> Yes, 1 -> Not Maintained
+ if (item.columnName === 'risk_data_maint') {
+ if (item.value === '0') return 'Yes';
+ if (item.value === '1') return 'Not Maintained';
+ }
+ return item.narrative || STATUS_LABELS[item.value ?? ''] || item.value || '-';
+}
+
+function RiskStatusGrid({ items }: { items: IndicatorStatusResponse[] }) {
+ // Risk Data Maintained 체크: Not Maintained(1)이면 해당 지표만 표시
+ const riskDataMaintained = items.find((i) => i.columnName === 'risk_data_maint');
+ const isNotMaintained = riskDataMaintained?.value === '1';
+
+ const displayItems = isNotMaintained
+ ? items.filter((i) => i.columnName === 'risk_data_maint')
+ : items;
+
+ const categories = useMemo(() => {
+ const map = new Map();
+ for (const item of displayItems) {
+ const cat = item.category || 'Other';
+ if (!map.has(cat)) map.set(cat, []);
+ map.get(cat)!.push(item);
+ }
+ return Array.from(map.entries());
+ }, [displayItems]);
+
+ return (
+
+ {isNotMaintained && (
+
+ Risk Data is not maintained for this vessel. Only the maintenance status is shown.
+
+ )}
+
+ {categories.map(([category, catItems]) => (
+
+
+ {category}
+
+
+ {catItems.map((item) => {
+ const color = STATUS_COLORS[item.value ?? ''] ?? '#6b7280';
+ const label = getRiskLabel(item);
+ return (
+
+ {item.fieldName}
+ ●
+
+ {label}
+
+
+ );
+ })}
+
+
+ ))}
+
+
+ );
+}
+
+// 선박 Compliance 탭 분류
+const SHIP_COMPLIANCE_TABS: { key: string; label: string; match: (category: string) => boolean }[] = [
+ { key: 'sanctions', label: 'Sanctions', match: (cat) => cat.includes('Sanctions') || cat.includes('FATF') || cat.includes('Other Compliance') },
+ { key: 'portcalls', label: 'Port Calls', match: (cat) => cat === 'Port Calls' },
+ { key: 'sts', label: 'STS Activity', match: (cat) => cat === 'STS Activity' },
+ { key: 'suspicious', label: 'Suspicious Behavior', match: (cat) => cat === 'Suspicious Behavior' },
+];
+
+// Compliance 예외 처리
+function getComplianceLabel(item: IndicatorStatusResponse, isCompany: boolean): string | null {
+ // Parent Company 관련: null -> No Parent
+ if (item.value == null || item.value === '') {
+ if (item.fieldName.includes('Parent Company') || item.fieldName.includes('Parent company')) return 'No Parent';
+ if (isCompany && item.columnName === 'prnt_company_compliance_risk') return 'No Parent';
+ }
+ return null;
+}
+
+// 제외할 컬럼명
+const SHIP_COMPLIANCE_EXCLUDE = ['lgl_snths_sanction']; // Overall은 토글 헤더에 표시
+const COMPANY_COMPLIANCE_EXCLUDE = ['company_snths_compliance_status']; // Overall은 토글 헤더에 표시
+
+function ComplianceStatusItem({ item, isCompany }: { item: IndicatorStatusResponse; isCompany: boolean }) {
+ const overrideLabel = getComplianceLabel(item, isCompany);
+ const status = overrideLabel ? null : COMPLIANCE_STATUS[item.value ?? ''];
+ const displayLabel = overrideLabel || (status ? status.label : (item.value ?? '-'));
+ const displayClass = overrideLabel
+ ? 'bg-wing-surface text-wing-muted border border-wing-border'
+ : status ? status.className : 'bg-wing-surface text-wing-muted border border-wing-border';
+
+ return (
+
+ {item.fieldName}
+
+ {displayLabel}
+
+
+ );
+}
+
+function ComplianceStatusGrid({ items, isCompany }: { items: IndicatorStatusResponse[]; isCompany: boolean }) {
+ const [activeTab, setActiveTab] = useState('sanctions');
+
+ // 제외 항목 필터링
+ const excludeList = isCompany ? COMPANY_COMPLIANCE_EXCLUDE : SHIP_COMPLIANCE_EXCLUDE;
+ const filteredItems = items.filter((i) => !excludeList.includes(i.columnName));
+
+ // 회사: 탭 없이 2컬럼 그리드
+ if (isCompany) {
+ const categories = useMemo(() => {
+ const map = new Map();
+ for (const item of filteredItems) {
+ const cat = item.category || 'Other';
+ if (!map.has(cat)) map.set(cat, []);
+ map.get(cat)!.push(item);
+ }
+ return Array.from(map.entries());
+ }, [filteredItems]);
+
+ return (
+
+ {categories.map(([category, catItems]) => (
+
+ {categories.length > 1 && (
+
+ {category}
+
+ )}
+
+ {catItems.map((item) => (
+
+ ))}
+
+
+ ))}
+
+ );
+ }
+
+ // 선박: 탭 기반 분류
+ const tabData = useMemo(() => {
+ const result: Record = {};
+ for (const tab of SHIP_COMPLIANCE_TABS) {
+ result[tab.key] = filteredItems.filter((i) => tab.match(i.category));
+ }
+ return result;
+ }, [filteredItems]);
+
+ const currentItems = tabData[activeTab] ?? [];
+
+ // 현재 탭 내 카테고리별 그룹핑
+ const categories = useMemo(() => {
+ const map = new Map();
+ for (const item of currentItems) {
+ const cat = item.category || 'Other';
+ if (!map.has(cat)) map.set(cat, []);
+ map.get(cat)!.push(item);
+ }
+ return Array.from(map.entries());
+ }, [currentItems]);
+
+ return (
+
+ {/* 탭 버튼 */}
+
+ {SHIP_COMPLIANCE_TABS.map((tab) => (
+ setActiveTab(tab.key)}
+ className={`px-3 py-1.5 rounded-lg text-[11px] font-bold transition-all border ${
+ activeTab === tab.key
+ ? 'bg-slate-900 text-white border-slate-900'
+ : 'bg-wing-card text-wing-muted border-wing-border hover:text-wing-text hover:bg-wing-hover'
+ }`}
+ >
+ {tab.label} ({tabData[tab.key]?.length ?? 0})
+
+ ))}
+
+
+ {/* 현재 탭 내용 */}
+ {currentItems.length > 0 ? (
+
+ {categories.map(([category, catItems]) => (
+
+ {categories.length > 1 && (
+
+ {category}
+
+ )}
+
+ {catItems.map((item) => (
+
+ ))}
+
+
+ ))}
+
+ ) : (
+
해당 항목이 없습니다.
+ )}
+
+ );
+}
+
+export default function HistoryTab({ lang }: HistoryTabProps) {
+ const [historyType, setHistoryType] = useState('ship-risk');
+ const [searchValue, setSearchValue] = useState('');
+ const [cache, setCache] = useState>({});
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+ const [searched, setSearched] = useState(false);
+ const [expandedDates, setExpandedDates] = useState>(new Set());
+ const [shipInfo, setShipInfo] = useState(null);
+ const [companyInfo, setCompanyInfo] = useState(null);
+ const [riskStatusCache, setRiskStatusCache] = useState>({});
+ const [complianceStatusCache, setComplianceStatusCache] = useState>({});
+ const [expandedSections, setExpandedSections] = useState>(new Set(['info', 'risk', 'compliance', 'history']));
+
+ const currentType = HISTORY_TYPES.find((t) => t.key === historyType)!;
+ const isRisk = historyType === 'ship-risk';
+ const data = cache[lang] ?? [];
+ const riskStatus = riskStatusCache[lang] ?? [];
+ const complianceStatus = complianceStatusCache[lang] ?? [];
+
+ const grouped: GroupedHistory[] = useMemo(() => {
+ const map = new Map();
+ for (const item of data) {
+ const key = item.lastModifiedDate;
+ if (!map.has(key)) map.set(key, []);
+ map.get(key)!.push(item);
+ }
+ return Array.from(map.entries()).map(([date, items]) => {
+ const overallColumn = currentType.overallColumn;
+ if (overallColumn) {
+ const overallItem = items.find((item) => item.changedColumnName === overallColumn);
+ return {
+ lastModifiedDate: date,
+ items,
+ overallBefore: overallItem?.beforeValue ?? null,
+ overallAfter: overallItem?.afterValue ?? null,
+ };
+ }
+ return { lastModifiedDate: date, items, overallBefore: null, overallAfter: null };
+ });
+ }, [data, currentType.overallColumn]);
+
+ function handleSearch() {
+ const trimmed = searchValue.trim();
+ if (!trimmed) return;
+ setLoading(true);
+ setError(null);
+ setSearched(true);
+ setExpandedDates(new Set());
+ setExpandedSections(new Set(['info', 'risk', 'compliance', 'history']));
+
+ const isShip = historyType !== 'company-compliance';
+ const showRisk = historyType === 'ship-risk';
+
+ const getHistoryCall = (l: string) =>
+ historyType === 'ship-risk'
+ ? screeningGuideApi.getShipRiskHistory(trimmed, l)
+ : historyType === 'ship-compliance'
+ ? screeningGuideApi.getShipComplianceHistory(trimmed, l)
+ : screeningGuideApi.getCompanyComplianceHistory(trimmed, l);
+
+ const promises: Promise[] = [
+ getHistoryCall('KO'),
+ getHistoryCall('EN'),
+ ];
+
+ if (isShip) {
+ promises.push(
+ screeningGuideApi.getShipInfo(trimmed),
+ screeningGuideApi.getShipComplianceStatus(trimmed, 'KO'),
+ screeningGuideApi.getShipComplianceStatus(trimmed, 'EN'),
+ );
+ if (showRisk) {
+ promises.push(
+ screeningGuideApi.getShipRiskStatus(trimmed, 'KO'),
+ screeningGuideApi.getShipRiskStatus(trimmed, 'EN'),
+ );
+ }
+ } else {
+ promises.push(
+ screeningGuideApi.getCompanyInfo(trimmed),
+ screeningGuideApi.getCompanyComplianceStatus(trimmed, 'KO'),
+ screeningGuideApi.getCompanyComplianceStatus(trimmed, 'EN'),
+ );
+ }
+
+ Promise.all(promises)
+ .then((results) => {
+ setCache({ KO: results[0].data ?? [], EN: results[1].data ?? [] });
+ if (isShip) {
+ setShipInfo(results[2].data);
+ setCompanyInfo(null);
+ setComplianceStatusCache({ KO: results[3].data ?? [], EN: results[4].data ?? [] });
+ if (showRisk) {
+ setRiskStatusCache({ KO: results[5].data ?? [], EN: results[6].data ?? [] });
+ } else {
+ setRiskStatusCache({});
+ }
+ } else {
+ setShipInfo(null);
+ setCompanyInfo(results[2].data);
+ setRiskStatusCache({});
+ setComplianceStatusCache({ KO: results[3].data ?? [], EN: results[4].data ?? [] });
+ }
+ })
+ .catch((err: Error) => setError(err.message))
+ .finally(() => setLoading(false));
+ }
+
+ function handleKeyDown(e: React.KeyboardEvent) {
+ if (e.key === 'Enter') handleSearch();
+ }
+
+ function handleTypeChange(type: HistoryType) {
+ setHistoryType(type);
+ setSearchValue('');
+ setCache({});
+ setError(null);
+ setSearched(false);
+ setExpandedDates(new Set());
+ setShipInfo(null);
+ setCompanyInfo(null);
+ setRiskStatusCache({});
+ setComplianceStatusCache({});
+ setExpandedSections(new Set(['info', 'risk', 'compliance', 'history']));
+ }
+
+ function toggleSection(section: string) {
+ setExpandedSections((prev) => {
+ const next = new Set(prev);
+ if (next.has(section)) next.delete(section);
+ else next.add(section);
+ return next;
+ });
+ }
+
+ function toggleDate(date: string) {
+ setExpandedDates((prev) => {
+ const next = new Set(prev);
+ if (next.has(date)) next.delete(date);
+ else next.add(date);
+ return next;
+ });
+ }
+
+ return (
+
+ {/* 이력 유형 선택 */}
+
+ {HISTORY_TYPES.map((t) => (
+ handleTypeChange(t.key)}
+ className={`px-4 py-2 rounded-lg text-sm font-bold transition-all border ${
+ historyType === t.key
+ ? 'bg-slate-900 text-white border-slate-900 shadow-md'
+ : 'bg-wing-card text-wing-muted border-wing-border hover:text-wing-text hover:bg-wing-hover'
+ }`}
+ >
+ {t.label}
+
+ ))}
+
+
+ {/* 검색 */}
+
+
+
+
+
+
+
+
setSearchValue(e.target.value)}
+ onKeyDown={handleKeyDown}
+ placeholder={currentType.searchPlaceholder}
+ className="w-full pl-10 pr-8 py-2 border border-wing-border rounded-lg text-sm
+ focus:ring-2 focus:ring-wing-accent focus:border-wing-accent outline-none"
+ />
+ {searchValue && (
+
setSearchValue('')}
+ className="absolute inset-y-0 right-3 flex items-center text-wing-muted hover:text-wing-text"
+ >
+
+
+
+
+ )}
+
+
+ {loading ? '조회 중...' : '조회'}
+
+
+
+ {/* 에러 */}
+ {error && (
+
+ 조회 실패: {error}
+
+ )}
+
+ {/* 결과: 3개 섹션 */}
+ {searched && !loading && !error && (
+
+ {/* Section 1: 기본 정보 */}
+ {(shipInfo || companyInfo) && (
+
+
toggleSection('info')}
+ className="w-full flex items-center gap-3 px-4 py-3 hover:bg-wing-hover transition-colors"
+ >
+ ▶
+
+ {shipInfo ? '선박 기본 정보' : '회사 기본 정보'}
+
+
+ {expandedSections.has('info') && (
+
+ {shipInfo && (
+
+ {/* 좌측: 핵심 식별 정보 */}
+
+
+
{shipInfo.shipName || '-'}
+
+
+
+ IMO
+ {shipInfo.imoNo}
+
+
+ MMSI
+ {shipInfo.mmsiNo || '-'}
+
+
+ Status
+ {shipInfo.shipStatus || '-'}
+
+
+
+
+ {/* 구분선 */}
+
+
+ {/* 우측: 스펙 정보 */}
+
+
+ 국적
+
+ {countryFlag(shipInfo.nationalityIsoCode)} {shipInfo.nationality || '-'}
+
+
+
+ 선종
+ {shipInfo.shipType || '-'}
+
+
+ DWT
+ {shipInfo.dwt || '-'}
+
+
+ GT
+ {shipInfo.gt || '-'}
+
+
+ 건조연도
+ {shipInfo.buildYear || '-'}
+
+
+
+ )}
+ {companyInfo && (
+
+ {/* 좌측: 핵심 식별 정보 */}
+
+
+
{companyInfo.fullName || '-'}
+ {companyInfo.abbreviation && (
+
{companyInfo.abbreviation}
+ )}
+
+
+
+ Code
+ {companyInfo.companyCode}
+
+
+ Status
+ {companyInfo.status || '-'}
+
+ {companyInfo.parentCompanyName && (
+
+ 모회사
+ {companyInfo.parentCompanyName}
+
+ )}
+
+
+
+ {/* 구분선 */}
+
+
+ {/* 우측: 상세 정보 */}
+
+
+ 등록국가
+
+ {countryFlag(companyInfo.registrationCountryIsoCode)} {companyInfo.registrationCountry || '-'}
+
+
+ {companyInfo.controlCountry && (
+
+ 관리국가
+
+ {countryFlag(companyInfo.controlCountryIsoCode)} {companyInfo.controlCountry}
+
+
+ )}
+ {companyInfo.foundedDate && (
+
+ 설립일
+ {companyInfo.foundedDate}
+
+ )}
+ {companyInfo.email && (
+
+ 이메일
+ {companyInfo.email}
+
+ )}
+ {companyInfo.phone && (
+
+ 전화
+ {companyInfo.phone}
+
+ )}
+ {companyInfo.website && (
+
+ )}
+
+
+ )}
+
+ )}
+
+ )}
+
+ {/* Section 2: Current Risk Indicators (선박 탭만) */}
+ {riskStatus.length > 0 && (
+
+
toggleSection('risk')}
+ className="w-full flex items-center gap-3 px-4 py-3 hover:bg-wing-hover transition-colors"
+ >
+ ▶
+ Current Risk Indicators
+
+ {expandedSections.has('risk') && (
+
+
+
+ )}
+
+ )}
+
+ {/* Section 3: Current Compliance (선박 제재/회사 제재 탭만) */}
+ {complianceStatus.length > 0 && !isRisk && (() => {
+ const isCompany = historyType === 'company-compliance';
+ const overallItem = isCompany
+ ? complianceStatus.find((i) => i.columnName === 'company_snths_compliance_status')
+ : null;
+ return (
+
+
toggleSection('compliance')}
+ className="w-full flex items-center gap-3 px-4 py-3 hover:bg-wing-hover transition-colors"
+ >
+ ▶
+ Current Compliance
+ {overallItem && (
+
+ )}
+
+ {expandedSections.has('compliance') && (
+
+
+
+ )}
+
+ );
+ })()}
+
+ {/* Section 4: 값 변경 이력 */}
+
+
toggleSection('history')}
+ className="w-full flex items-center gap-3 px-4 py-3 hover:bg-wing-hover transition-colors"
+ >
+ ▶
+ 값 변경 이력
+
+ {grouped.length}개 일시, {data.length}건 변동
+
+
+ {expandedSections.has('history') && (
+
+ {grouped.length > 0 ? (
+
+ {grouped.map((group) => {
+ const isExpanded = expandedDates.has(group.lastModifiedDate);
+ const hasOverall =
+ group.overallBefore != null || group.overallAfter != null;
+ const displayItems = (currentType.overallColumn
+ ? group.items.filter(
+ (item) => item.changedColumnName !== currentType.overallColumn,
+ )
+ : [...group.items]
+ ).sort((a, b) => (a.sortOrder ?? Infinity) - (b.sortOrder ?? Infinity));
+
+ return (
+
+
toggleDate(group.lastModifiedDate)}
+ className="w-full flex items-center justify-between px-4 py-3 hover:bg-wing-hover transition-colors"
+ >
+
+
+ ▶
+
+
Change Date :
+
+ {group.lastModifiedDate}
+
+ {hasOverall ? (
+
+
+ →
+
+
+ ) : (
+
+ {displayItems.length}건 변동
+
+ )}
+
+ {hasOverall && (
+
+ {displayItems.length}건 변동
+
+ )}
+
+ {isExpanded && displayItems.length > 0 && (
+
+
+
+
+
+ 필드명
+
+
+ 이전값
+
+
+ 이후값
+
+
+
+
+ {displayItems.map((row) => (
+
+
+
+ {row.fieldName || row.changedColumnName}
+
+ {row.fieldName && (
+
+ {row.changedColumnName}
+
+ )}
+
+ {isRisk ? (
+ <>
+
+
+
+
+
+
+ >
+ ) : (
+ <>
+
+
+
+
+
+
+ >
+ )}
+
+ ))}
+
+
+
+ )}
+
+ );
+ })}
+
+ ) : (
+
+ )}
+
+ )}
+
+
+ )}
+
+ {/* 초기 상태 */}
+ {!searched && (
+
+
+
🔍
+
{currentType.searchLabel}을(를) 입력하고 조회하세요.
+
+
+ )}
+
+ );
+}
diff --git a/frontend/src/components/screening/MethodologyTab.tsx b/frontend/src/components/screening/MethodologyTab.tsx
new file mode 100644
index 0000000..fb9aa14
--- /dev/null
+++ b/frontend/src/components/screening/MethodologyTab.tsx
@@ -0,0 +1,174 @@
+import { useState, useEffect } from 'react';
+import { screeningGuideApi, type MethodologyHistoryResponse } from '../../api/screeningGuideApi';
+
+interface MethodologyTabProps {
+ lang: string;
+}
+
+const CHANGE_TYPE_COLORS: Record = {
+ Addition: '#065f46',
+ Update: '#1d4ed8',
+ Expansion: '#6b21a8',
+ Change: '#92400e',
+ Removal: '#991b1b',
+ New: '#0f766e',
+};
+
+function getChangeTypeColor(changeType: string): string {
+ return CHANGE_TYPE_COLORS[changeType] ?? '#374151';
+}
+
+export default function MethodologyTab({ lang }: MethodologyTabProps) {
+ const [history, setHistory] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+ const [selectedType, setSelectedType] = useState('전체');
+
+ useEffect(() => {
+ setLoading(true);
+ setError(null);
+ screeningGuideApi
+ .getMethodologyHistory(lang)
+ .then((res) => setHistory(res.data ?? []))
+ .catch((err: Error) => setError(err.message))
+ .finally(() => setLoading(false));
+ }, [lang]);
+
+ const sortedHistory = [...history].sort((a, b) =>
+ b.changeDate.localeCompare(a.changeDate),
+ );
+
+ const uniqueTypes = Array.from(new Set(history.map((h) => h.changeType)));
+
+ const filtered =
+ selectedType === '전체'
+ ? sortedHistory
+ : sortedHistory.filter((h) => h.changeType === selectedType);
+
+ if (loading) {
+ return (
+
+ );
+ }
+
+ if (error) {
+ return (
+
+ 데이터 로딩 실패: {error}
+
+ );
+ }
+
+ return (
+
+ {/* 주의사항 배너 */}
+
+ 이력 관리 주의사항: 방법론 변경은 선박·기업의 컴플라이언스
+ 상태값을 자동으로 변경시킵니다. 상태 변경이 실제 리스크 변화인지, 방법론
+ 업데이트 때문인지 반드시 교차 확인해야 합니다.
+
+
+ {/* 변경 유형 필터 */}
+
+ setSelectedType('전체')}
+ className={`px-3 py-1 rounded-full text-[11px] font-bold transition-colors border ${
+ selectedType === '전체'
+ ? 'bg-slate-900 text-white border-slate-900'
+ : 'bg-wing-card text-wing-muted border-wing-border hover:text-wing-text'
+ }`}
+ >
+ 전체 ({history.length})
+
+ {uniqueTypes.map((type) => {
+ const count = history.filter((h) => h.changeType === type).length;
+ const hex = getChangeTypeColor(type);
+ const isActive = selectedType === type;
+ return (
+ setSelectedType(isActive ? '전체' : type)}
+ className="px-3 py-1 rounded-full text-[11px] font-bold transition-all border"
+ style={{
+ background: isActive ? hex : undefined,
+ borderColor: isActive ? hex : undefined,
+ color: isActive ? 'white' : undefined,
+ }}
+ >
+ {type} ({count})
+
+ );
+ })}
+
+
+
+ 표시: {filtered.length} 건 | 최신순 정렬
+
+
+ {/* 타임라인 목록 */}
+
+
+
+
+
+ {['날짜', '변경 유형', '제목', '설명', '참고사항'].map((h) => (
+
+ {h}
+
+ ))}
+
+
+
+ {filtered.map((row, i) => {
+ const hex = getChangeTypeColor(row.changeType);
+ return (
+
+
+
+ {row.changeDate}
+
+
+
+
+ {row.changeType}
+
+
+
+ {row.updateTitle}
+
+
+ {row.description}
+
+
+ {row.collectionNote && `💡 ${row.collectionNote}`}
+
+
+ );
+ })}
+
+
+
+
+
+ {filtered.length === 0 && (
+
+ 해당 유형의 변경 이력이 없습니다.
+
+ )}
+
+ );
+}
diff --git a/frontend/src/components/screening/RiskTab.tsx b/frontend/src/components/screening/RiskTab.tsx
new file mode 100644
index 0000000..92b6e40
--- /dev/null
+++ b/frontend/src/components/screening/RiskTab.tsx
@@ -0,0 +1,349 @@
+import { useState, useEffect } from 'react';
+import { screeningGuideApi, type RiskCategoryResponse, type RiskIndicatorResponse } from '../../api/screeningGuideApi';
+
+interface RiskTabProps {
+ lang: string;
+}
+
+type ViewMode = 'table' | 'card';
+
+const CAT_COLORS: Record = {
+ 'AIS': 'bg-blue-800',
+ 'Port Calls': 'bg-emerald-800',
+ 'Associated with Russia': 'bg-red-800',
+ 'Behavioural Risk': 'bg-amber-800',
+ 'Safety, Security & Inspections': 'bg-blue-600',
+ 'Flag Risk': 'bg-purple-800',
+ 'Owner & Classification': 'bg-teal-700',
+};
+
+const CAT_HEX: Record = {
+ 'AIS': '#1e40af',
+ 'Port Calls': '#065f46',
+ 'Associated with Russia': '#991b1b',
+ 'Behavioural Risk': '#92400e',
+ 'Safety, Security & Inspections': '#1d4ed8',
+ 'Flag Risk': '#6b21a8',
+ 'Owner & Classification': '#0f766e',
+};
+
+function getCatColor(categoryName: string): string {
+ return CAT_COLORS[categoryName] ?? 'bg-slate-700';
+}
+
+function getCatHex(categoryName: string): string {
+ return CAT_HEX[categoryName] ?? '#374151';
+}
+
+interface FlatRow {
+ category: string;
+ indicator: RiskIndicatorResponse;
+}
+
+export default function RiskTab({ lang }: RiskTabProps) {
+ const [categories, setCategories] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+ const [selectedCategory, setSelectedCategory] = useState('전체');
+ const [viewMode, setViewMode] = useState('table');
+
+ useEffect(() => {
+ setLoading(true);
+ setError(null);
+ screeningGuideApi
+ .getRiskIndicators(lang)
+ .then((res) => setCategories(res.data ?? []))
+ .catch((err: Error) => setError(err.message))
+ .finally(() => setLoading(false));
+ }, [lang]);
+
+ const flatRows: FlatRow[] = categories.flatMap((cat) =>
+ cat.indicators.map((ind) => ({ category: cat.categoryName, indicator: ind })),
+ );
+
+ const filtered: FlatRow[] =
+ selectedCategory === '전체'
+ ? flatRows
+ : flatRows.filter((r) => r.category === selectedCategory);
+
+ function downloadCSV() {
+ const bom = '\uFEFF';
+ const headers = [
+ '카테고리',
+ '필드키',
+ '필드명',
+ '설명',
+ 'RED 조건',
+ 'AMBER 조건',
+ 'GREEN 조건',
+ '데이터 타입',
+ '이력 관리 참고사항',
+ ];
+ const rows = flatRows.map((r) =>
+ [
+ r.category,
+ r.indicator.fieldKey,
+ r.indicator.fieldName,
+ r.indicator.description,
+ r.indicator.conditionRed,
+ r.indicator.conditionAmber,
+ r.indicator.conditionGreen,
+ r.indicator.dataType,
+ r.indicator.collectionNote,
+ ]
+ .map((v) => `"${(v ?? '').replace(/"/g, '""')}"`)
+ .join(','),
+ );
+ const csv = bom + [headers.join(','), ...rows].join('\n');
+ const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
+ const a = document.createElement('a');
+ a.href = URL.createObjectURL(blob);
+ a.download = 'MIRS_Risk_Indicators.csv';
+ a.click();
+ }
+
+ if (loading) {
+ return (
+
+ );
+ }
+
+ if (error) {
+ return (
+
+ 데이터 로딩 실패: {error}
+
+ );
+ }
+
+ return (
+
+ {/* 카테고리 요약 카드 */}
+
+ {categories.map((cat) => {
+ const isActive = selectedCategory === cat.categoryName;
+ const hex = getCatHex(cat.categoryName);
+ return (
+
+ setSelectedCategory(isActive ? '전체' : cat.categoryName)
+ }
+ className="rounded-lg p-3 text-center cursor-pointer transition-all border-2"
+ style={{
+ background: isActive ? hex : undefined,
+ borderColor: isActive ? hex : undefined,
+ }}
+ >
+
+ {cat.indicators.length}
+
+
+ {cat.categoryName}
+
+
+ );
+ })}
+
+
+ {/* 컨트롤 바 */}
+
+
setSelectedCategory('전체')}
+ className={`px-4 py-1.5 rounded-full text-xs font-bold transition-colors border ${
+ selectedCategory === '전체'
+ ? 'bg-slate-900 text-white border-slate-900'
+ : 'bg-wing-card text-wing-muted border-wing-border hover:text-wing-text'
+ }`}
+ >
+ 전체 ({flatRows.length})
+
+
+
+ 표시:{' '}
+ {filtered.length} 개 항목
+
+
setViewMode(viewMode === 'table' ? 'card' : 'table')}
+ className="px-3 py-1.5 rounded-lg border border-wing-border bg-wing-card text-wing-muted text-xs font-semibold hover:text-wing-text transition-colors"
+ >
+ {viewMode === 'table' ? '📋 카드 보기' : '📊 테이블 보기'}
+
+
+ ⬇ CSV 다운로드
+
+
+
+ {/* 테이블 뷰 */}
+ {viewMode === 'table' && (
+
+
+
+
+
+ {[
+ '카테고리',
+ '필드명',
+ '설명',
+ '🔴 RED',
+ '🟡 AMBER',
+ '🟢 GREEN',
+ '데이터 타입',
+ '이력 관리 참고',
+ ].map((h) => (
+
+ {h}
+
+ ))}
+
+
+
+ {filtered.map((row, i) => {
+ const showCat =
+ i === 0 ||
+ filtered[i - 1].category !== row.category;
+ const hex = getCatHex(row.category);
+ return (
+
+
+ {showCat && (
+
+ {row.category}
+
+ )}
+
+
+
+ {row.indicator.fieldName}
+
+
+ {row.indicator.fieldKey}
+
+
+
+ {row.indicator.description}
+
+
+
+ {row.indicator.conditionRed}
+
+
+
+
+ {row.indicator.conditionAmber}
+
+
+
+
+ {row.indicator.conditionGreen}
+
+
+
+ {row.indicator.dataType}
+
+
+ {row.indicator.collectionNote &&
+ `💡 ${row.indicator.collectionNote}`}
+
+
+ );
+ })}
+
+
+
+
+ )}
+
+ {/* 카드 뷰 */}
+ {viewMode === 'card' && (
+
+ {filtered.map((row, i) => {
+ const hex = getCatHex(row.category);
+ const colorClass = getCatColor(row.category);
+ return (
+
+
+
+ {row.category}
+
+
+ {row.indicator.dataType}
+
+
+
+
+ {row.indicator.fieldName}
+
+
+ {row.indicator.fieldKey}
+
+
+ {row.indicator.description}
+
+
+
+
+ 🔴 RED
+
+
+ {row.indicator.conditionRed}
+
+
+
+
+ 🟡 AMBER
+
+
+ {row.indicator.conditionAmber}
+
+
+
+
+ 🟢 GREEN
+
+
+ {row.indicator.conditionGreen}
+
+
+
+ {row.indicator.collectionNote && (
+
+ 💡 {row.indicator.collectionNote}
+
+ )}
+
+
+ );
+ })}
+
+ )}
+
+ );
+}
diff --git a/frontend/src/pages/BypassConfig.tsx b/frontend/src/pages/BypassConfig.tsx
new file mode 100644
index 0000000..a1ea498
--- /dev/null
+++ b/frontend/src/pages/BypassConfig.tsx
@@ -0,0 +1,507 @@
+import { useState, useEffect, useCallback, useMemo } from 'react';
+import {
+ bypassApi,
+ type BypassConfigRequest,
+ type BypassConfigResponse,
+ type CodeGenerationResult,
+ type WebClientBeanInfo,
+} from '../api/bypassApi';
+import { useToastContext } from '../contexts/ToastContext';
+import BypassConfigModal from '../components/bypass/BypassConfigModal';
+import ConfirmModal from '../components/ConfirmModal';
+import InfoModal from '../components/InfoModal';
+import LoadingSpinner from '../components/LoadingSpinner';
+
+interface ConfirmAction {
+ type: 'delete' | 'generate';
+ config: BypassConfigResponse;
+}
+
+type ViewMode = 'card' | 'table';
+
+const HTTP_METHOD_COLORS: Record = {
+ GET: 'bg-emerald-100 text-emerald-700',
+ POST: 'bg-blue-100 text-blue-700',
+ PUT: 'bg-amber-100 text-amber-700',
+ DELETE: 'bg-red-100 text-red-700',
+};
+
+export default function BypassConfig() {
+ const { showToast } = useToastContext();
+
+ const [configs, setConfigs] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [webclientBeans, setWebclientBeans] = useState([]);
+ const [viewMode, setViewMode] = useState('table');
+ const [searchTerm, setSearchTerm] = useState('');
+ const [selectedDomain, setSelectedDomain] = useState('');
+
+ const [modalOpen, setModalOpen] = useState(false);
+ const [editConfig, setEditConfig] = useState(null);
+
+ const [confirmAction, setConfirmAction] = useState(null);
+ const [generationResult, setGenerationResult] = useState(null);
+
+ const loadConfigs = useCallback(async () => {
+ try {
+ const res = await bypassApi.getConfigs();
+ setConfigs(res.data ?? []);
+ } catch (err) {
+ showToast('Bypass API 목록 조회 실패', 'error');
+ console.error(err);
+ } finally {
+ setLoading(false);
+ }
+ }, [showToast]);
+
+ useEffect(() => {
+ loadConfigs();
+ bypassApi.getWebclientBeans()
+ .then((res) => setWebclientBeans(res.data ?? []))
+ .catch((err) => console.error(err));
+ }, [loadConfigs]);
+
+ const handleCreate = () => {
+ setEditConfig(null);
+ setModalOpen(true);
+ };
+
+ const handleEdit = (config: BypassConfigResponse) => {
+ setEditConfig(config);
+ setModalOpen(true);
+ };
+
+ const handleSave = async (data: BypassConfigRequest) => {
+ if (editConfig) {
+ await bypassApi.updateConfig(editConfig.id, data);
+ showToast('Bypass API가 수정되었습니다.', 'success');
+ } else {
+ await bypassApi.createConfig(data);
+ showToast('Bypass API가 등록되었습니다.', 'success');
+ }
+ await loadConfigs();
+ };
+
+ const handleDeleteConfirm = async () => {
+ if (!confirmAction || confirmAction.type !== 'delete') return;
+ try {
+ await bypassApi.deleteConfig(confirmAction.config.id);
+ showToast('Bypass API가 삭제되었습니다.', 'success');
+ await loadConfigs();
+ } catch (err) {
+ showToast('삭제 실패', 'error');
+ console.error(err);
+ } finally {
+ setConfirmAction(null);
+ }
+ };
+
+ const handleGenerateConfirm = async () => {
+ if (!confirmAction || confirmAction.type !== 'generate') return;
+ const targetConfig = confirmAction.config;
+ setConfirmAction(null);
+ try {
+ const res = await bypassApi.generateCode(targetConfig.id, targetConfig.generated);
+ setGenerationResult(res.data);
+ showToast('코드가 생성되었습니다.', 'success');
+ await loadConfigs();
+ } catch (err) {
+ showToast('코드 생성 실패', 'error');
+ console.error(err);
+ }
+ };
+
+ const domainNames = useMemo(() => {
+ const names = [...new Set(configs.map((c) => c.domainName))];
+ return names.sort();
+ }, [configs]);
+
+ const filteredConfigs = useMemo(() => {
+ return configs.filter((c) => {
+ const matchesSearch =
+ !searchTerm.trim() ||
+ c.domainName.toLowerCase().includes(searchTerm.toLowerCase()) ||
+ c.displayName.toLowerCase().includes(searchTerm.toLowerCase());
+ const matchesDomain = !selectedDomain || c.domainName === selectedDomain;
+ return matchesSearch && matchesDomain;
+ });
+ }, [configs, searchTerm, selectedDomain]);
+
+ if (loading) return ;
+
+ return (
+
+ {/* 헤더 */}
+
+
+
Bypass API 관리
+
+ 외부 Maritime API를 직접 프록시하는 Bypass API를 등록하고 코드를 생성합니다.
+
+
+
+ + 새 API 등록
+
+
+
+ {/* 검색 + 뷰 전환 */}
+
+
+ {/* 검색 */}
+
+
+
+
+
+
+
setSearchTerm(e.target.value)}
+ className="w-full pl-10 pr-4 py-2 border border-wing-border rounded-lg text-sm
+ focus:ring-2 focus:ring-wing-accent focus:border-wing-accent outline-none bg-wing-surface text-wing-text"
+ />
+ {searchTerm && (
+
setSearchTerm('')}
+ className="absolute inset-y-0 right-3 flex items-center text-wing-muted hover:text-wing-text"
+ >
+
+
+
+
+ )}
+
+
+ {/* 도메인 드롭다운 필터 */}
+
setSelectedDomain(e.target.value)}
+ className="px-3 py-2 text-sm rounded-lg border border-wing-border bg-wing-surface text-wing-text"
+ >
+ 전체 도메인
+ {domainNames.map((name) => (
+ {name}
+ ))}
+
+
+ {/* 뷰 전환 토글 */}
+
+
setViewMode('table')}
+ title="테이블 보기"
+ className={`px-3 py-2 transition-colors ${
+ viewMode === 'table'
+ ? 'bg-wing-accent text-white'
+ : 'bg-wing-surface text-wing-muted hover:text-wing-text'
+ }`}
+ >
+
+
+
+
+
setViewMode('card')}
+ title="카드 보기"
+ className={`px-3 py-2 transition-colors border-l border-wing-border ${
+ viewMode === 'card'
+ ? 'bg-wing-accent text-white'
+ : 'bg-wing-surface text-wing-muted hover:text-wing-text'
+ }`}
+ >
+
+
+
+
+
+
+
+ {(searchTerm || selectedDomain) && (
+
+ {filteredConfigs.length}개 API 검색됨
+
+ )}
+
+
+ {/* 빈 상태 */}
+ {configs.length === 0 ? (
+
+
등록된 BYPASS API가 없습니다.
+
위 버튼을 눌러 새 API를 등록하세요.
+
+ ) : filteredConfigs.length === 0 ? (
+
+
검색 결과가 없습니다.
+
다른 검색어를 사용해 보세요.
+
+ ) : viewMode === 'card' ? (
+ /* 카드 뷰 */
+
+ {filteredConfigs.map((config) => (
+
+ {/* 카드 헤더 */}
+
+
+
{config.displayName}
+
{config.domainName}
+
+
+ {config.generated ? '생성 완료' : '미생성'}
+
+
+
+ {/* 카드 정보 */}
+
+
+
+ {config.httpMethod}
+
+
+ {config.externalPath}
+
+
+
+ WebClient: {' '}
+ {config.webclientBean}
+
+ {config.description && (
+
{config.description}
+ )}
+
+
+ {/* 카드 액션 */}
+
+ handleEdit(config)}
+ className="flex-1 py-1.5 text-xs font-medium text-wing-text bg-wing-surface hover:bg-wing-hover border border-wing-border rounded-lg transition-colors"
+ >
+ 수정
+
+ setConfirmAction({ type: 'generate', config })}
+ className="flex-1 py-1.5 text-xs font-medium text-white bg-wing-accent hover:bg-wing-accent/80 rounded-lg transition-colors"
+ >
+ {config.generated ? '재생성' : '코드 생성'}
+
+ setConfirmAction({ type: 'delete', config })}
+ className="py-1.5 px-3 text-xs font-medium text-red-500 hover:bg-red-50 border border-red-200 rounded-lg transition-colors"
+ >
+ 삭제
+
+
+
+ ))}
+
+ ) : (
+ /* 테이블 뷰 */
+
+
+
+
+
+
+ 도메인명
+
+
+ 표시명
+
+
+ HTTP 메서드
+
+
+ WebClient
+
+
+ 외부 경로
+
+
+ 생성 상태
+
+
+ 등록일
+
+
+ 액션
+
+
+
+
+ {filteredConfigs.map((config) => (
+
+
+ {config.domainName}
+
+
+ {config.displayName}
+
+
+
+ {config.httpMethod}
+
+
+
+ {config.webclientBean}
+
+
+ {config.externalPath}
+
+
+
+ {config.generated ? '생성 완료' : '미생성'}
+
+
+
+ {config.createdAt
+ ? new Date(config.createdAt).toLocaleDateString('ko-KR')
+ : '-'}
+
+
+
+ handleEdit(config)}
+ className="px-3 py-1.5 text-xs font-medium text-wing-text bg-wing-card hover:bg-wing-hover border border-wing-border rounded-lg transition-colors"
+ >
+ 수정
+
+ setConfirmAction({ type: 'generate', config })}
+ className="px-3 py-1.5 text-xs font-medium text-white bg-wing-accent hover:bg-wing-accent/80 rounded-lg transition-colors"
+ >
+ {config.generated ? '재생성' : '코드 생성'}
+
+ setConfirmAction({ type: 'delete', config })}
+ className="px-3 py-1.5 text-xs font-medium text-red-500 hover:bg-red-50 border border-red-200 rounded-lg transition-colors"
+ >
+ 삭제
+
+
+
+
+ ))}
+
+
+
+
+ )}
+
+ {/* 등록/수정 모달 */}
+
setModalOpen(false)}
+ />
+
+ {/* 삭제 확인 모달 */}
+ setConfirmAction(null)}
+ />
+
+ {/* 코드 생성 확인 모달 */}
+ setConfirmAction(null)}
+ />
+
+ {/* 코드 생성 결과 모달 */}
+ setGenerationResult(null)}
+ >
+ {generationResult && (
+
+
{generationResult.message}
+
+
생성된 파일
+
+ Controller
+ {generationResult.controllerPath}
+
+ {generationResult.servicePaths.map((path, idx) => (
+
+
+ Service {generationResult.servicePaths.length > 1 ? idx + 1 : ''}
+
+ {path}
+
+ ))}
+
+
+ ⚠
+ 서버를 재시작하면 새 API가 활성화됩니다.
+
+
+ )}
+
+
+ );
+}
diff --git a/frontend/src/pages/MainMenu.tsx b/frontend/src/pages/MainMenu.tsx
new file mode 100644
index 0000000..60a1723
--- /dev/null
+++ b/frontend/src/pages/MainMenu.tsx
@@ -0,0 +1,69 @@
+import { Link } from 'react-router-dom';
+import { useThemeContext } from '../contexts/ThemeContext';
+
+const sections = [
+ {
+ title: 'S&P Collector',
+ description: 'S&P 배치 수집 관리',
+ detail: '대시보드, 실행 이력, 재수집 이력, 작업 관리, 스케줄, 타임라인',
+ path: '/dashboard',
+ icon: '🔄',
+ iconClass: 'gc-card-icon',
+ menuCount: 6,
+ },
+ {
+ title: 'S&P Bypass',
+ description: 'S&P Bypass API 관리',
+ detail: 'API 등록, 코드 생성 관리, 테스트',
+ path: '/bypass-config',
+ icon: '🔗',
+ iconClass: 'gc-card-icon gc-card-icon-guide',
+ menuCount: 1,
+ },
+ {
+ title: 'S&P Risk & Compliance',
+ description: 'S&P 위험 지표 및 규정 준수',
+ detail: '위험 지표 및 규정 준수 가이드, 변경 이력 조회',
+ path: '/screening-guide',
+ icon: '⚖️',
+ iconClass: 'gc-card-icon gc-card-icon-nexus',
+ menuCount: 2,
+ },
+];
+
+export default function MainMenu() {
+ const { theme, toggle } = useThemeContext();
+
+ return (
+
+ {/* 헤더 */}
+
+
S&P Data Platform
+
해양 데이터 통합 관리 플랫폼
+
+
+ {/* 섹션 카드 */}
+
+ {sections.map((section) => (
+
+
+ {section.icon}
+
+
{section.title}
+
{section.description} {section.detail}
+
+ ))}
+
+
+ {/* 테마 토글 */}
+
+ {theme === 'dark' ? '☀️ 라이트 모드' : '🌙 다크 모드'}
+
+
+ );
+}
diff --git a/frontend/src/pages/RiskComplianceHistory.tsx b/frontend/src/pages/RiskComplianceHistory.tsx
new file mode 100644
index 0000000..04c900c
--- /dev/null
+++ b/frontend/src/pages/RiskComplianceHistory.tsx
@@ -0,0 +1,51 @@
+import { useState } from 'react';
+import HistoryTab from '../components/screening/HistoryTab';
+
+export default function RiskComplianceHistory() {
+ const [lang, setLang] = useState('KO');
+
+ return (
+
+ {/* 헤더 */}
+
+
+ S&P Global · Maritime Intelligence Risk Suite (MIRS)
+
+
+ Risk & Compliance Change History
+
+
+ 위험 지표 및 컴플라이언스 값 변경 이력
+
+
+
+ {/* 언어 토글 */}
+
+
+ setLang('EN')}
+ className={`px-3 py-1.5 text-xs font-bold transition-colors ${
+ lang === 'EN'
+ ? 'bg-slate-900 text-white'
+ : 'bg-wing-card text-wing-muted hover:text-wing-text'
+ }`}
+ >
+ EN
+
+ setLang('KO')}
+ className={`px-3 py-1.5 text-xs font-bold transition-colors ${
+ lang === 'KO'
+ ? 'bg-slate-900 text-white'
+ : 'bg-wing-card text-wing-muted hover:text-wing-text'
+ }`}
+ >
+ KO
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/pages/ScreeningGuide.tsx b/frontend/src/pages/ScreeningGuide.tsx
new file mode 100644
index 0000000..6f971dc
--- /dev/null
+++ b/frontend/src/pages/ScreeningGuide.tsx
@@ -0,0 +1,100 @@
+import { useState } from 'react';
+import RiskTab from '../components/screening/RiskTab';
+import ComplianceTab from '../components/screening/ComplianceTab';
+import MethodologyTab from '../components/screening/MethodologyTab';
+
+type ActiveTab = 'risk' | 'compliance' | 'methodology';
+
+interface TabButtonProps {
+ active: boolean;
+ onClick: () => void;
+ children: React.ReactNode;
+}
+
+function TabButton({ active, onClick, children }: TabButtonProps) {
+ return (
+
+ {children}
+
+ );
+}
+
+export default function ScreeningGuide() {
+ const [activeTab, setActiveTab] = useState('risk');
+ const [lang, setLang] = useState('KO');
+
+ return (
+
+ {/* 헤더 */}
+
+
+ S&P Global · Maritime Intelligence Risk Suite (MIRS)
+
+
+ Risk & Compliance Screening Guide
+
+
+ 위험 지표 및 컴플라이언스 심사 기준 가이드
+
+
+
+ {/* 탭 + 언어 토글 */}
+
+
+ setActiveTab('risk')}
+ >
+ Risk Indicators
+
+ setActiveTab('compliance')}
+ >
+ Compliance
+
+ setActiveTab('methodology')}
+ >
+ Methodology History
+
+
+
+ setLang('EN')}
+ className={`px-3 py-1.5 text-xs font-bold transition-colors ${
+ lang === 'EN'
+ ? 'bg-slate-900 text-white'
+ : 'bg-wing-card text-wing-muted hover:text-wing-text'
+ }`}
+ >
+ EN
+
+ setLang('KO')}
+ className={`px-3 py-1.5 text-xs font-bold transition-colors ${
+ lang === 'KO'
+ ? 'bg-slate-900 text-white'
+ : 'bg-wing-card text-wing-muted hover:text-wing-text'
+ }`}
+ >
+ KO
+
+
+
+
+ {/* 탭 내용 */}
+ {activeTab === 'risk' &&
}
+ {activeTab === 'compliance' &&
}
+ {activeTab === 'methodology' &&
}
+
+ );
+}
diff --git a/frontend/src/theme/base.css b/frontend/src/theme/base.css
index 803906a..7148406 100644
--- a/frontend/src/theme/base.css
+++ b/frontend/src/theme/base.css
@@ -23,3 +23,76 @@ body {
::-webkit-scrollbar-thumb:hover {
background: var(--wing-accent);
}
+
+/* Main Menu Cards */
+.gc-cards {
+ padding: 2rem 0;
+ display: flex;
+ justify-content: center;
+ align-items: stretch;
+ gap: 2rem;
+ width: 80%;
+ margin: 0 auto;
+}
+
+.gc-cards > * {
+ flex: 1 1 0;
+}
+
+.gc-card {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+ padding: 2.5rem 2rem;
+ border: 1px solid var(--wing-border);
+ border-radius: 12px;
+ background: var(--wing-surface);
+ text-decoration: none !important;
+ color: inherit !important;
+ transition: all 0.2s ease;
+ height: 100%;
+}
+
+.gc-card:hover {
+ border-color: #4183c4;
+ box-shadow: 0 4px 16px rgba(65, 131, 196, 0.15);
+ transform: translateY(-2px);
+}
+
+.gc-card-icon {
+ color: #4183c4;
+ margin-bottom: 1rem;
+}
+
+.gc-card-icon-guide {
+ color: #21ba45;
+}
+
+.gc-card-icon-nexus {
+ color: #f2711c;
+}
+
+.gc-card h3 {
+ font-size: 1.3rem;
+ margin-bottom: 0.5rem;
+ color: var(--wing-text);
+}
+
+.gc-card p {
+ font-size: 0.95rem;
+ color: var(--wing-muted);
+ line-height: 1.5;
+ margin-bottom: 1rem;
+}
+
+.gc-card-link {
+ font-size: 0.9rem;
+ color: #4183c4;
+ font-weight: 600;
+ margin-top: auto;
+}
+
+.gc-card:hover .gc-card-link {
+ text-decoration: underline;
+}
diff --git a/src/main/java/com/snp/batch/common/web/controller/BaseBypassController.java b/src/main/java/com/snp/batch/common/web/controller/BaseBypassController.java
new file mode 100644
index 0000000..7563d2e
--- /dev/null
+++ b/src/main/java/com/snp/batch/common/web/controller/BaseBypassController.java
@@ -0,0 +1,28 @@
+package com.snp.batch.common.web.controller;
+
+import com.snp.batch.common.web.ApiResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
+
+import java.util.function.Supplier;
+
+@Slf4j
+public abstract class BaseBypassController {
+
+ protected ResponseEntity> execute(Supplier action) {
+ try {
+ T result = action.get();
+ return ResponseEntity.ok(ApiResponse.success(result));
+ } catch (WebClientResponseException e) {
+ log.error("외부 API 호출 실패 - status: {}, body: {}",
+ e.getStatusCode(), e.getResponseBodyAsString());
+ return ResponseEntity.status(e.getStatusCode())
+ .body(ApiResponse.error("외부 API 호출 실패: " + e.getMessage()));
+ } catch (Exception e) {
+ log.error("API 처리 중 오류", e);
+ return ResponseEntity.internalServerError()
+ .body(ApiResponse.error("처리 실패: " + e.getMessage()));
+ }
+ }
+}
diff --git a/src/main/java/com/snp/batch/common/web/service/BaseBypassService.java b/src/main/java/com/snp/batch/common/web/service/BaseBypassService.java
new file mode 100644
index 0000000..fac1099
--- /dev/null
+++ b/src/main/java/com/snp/batch/common/web/service/BaseBypassService.java
@@ -0,0 +1,131 @@
+package com.snp.batch.common.web.service;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.util.UriBuilder;
+
+import java.net.URI;
+import java.util.List;
+import java.util.function.Function;
+
+@Slf4j
+public abstract class BaseBypassService {
+
+ private final WebClient webClient;
+ private final String apiPath;
+ private final String displayName;
+ private final ParameterizedTypeReference> listTypeRef;
+ private final ParameterizedTypeReference singleTypeRef;
+
+ protected BaseBypassService(WebClient webClient, String apiPath, String displayName,
+ ParameterizedTypeReference> listTypeRef,
+ ParameterizedTypeReference singleTypeRef) {
+ this.webClient = webClient;
+ this.apiPath = apiPath;
+ this.displayName = displayName;
+ this.listTypeRef = listTypeRef;
+ this.singleTypeRef = singleTypeRef;
+ }
+
+ protected List fetchGetList(Function uriFunction) {
+ log.info("{} API GET 호출", displayName);
+ List response = webClient.get()
+ .uri(uriFunction)
+ .retrieve()
+ .bodyToMono(listTypeRef)
+ .block();
+ if (response == null || response.isEmpty()) {
+ log.warn("{} API 응답 없음", displayName);
+ return List.of();
+ }
+ log.info("{} API 응답 완료 - 건수: {}", displayName, response.size());
+ return response;
+ }
+
+ protected T fetchGetOne(Function uriFunction) {
+ log.info("{} API GET 호출 (단건)", displayName);
+ T response = webClient.get()
+ .uri(uriFunction)
+ .retrieve()
+ .bodyToMono(singleTypeRef)
+ .block();
+ if (response == null) {
+ log.warn("{} API 응답 없음", displayName);
+ return null;
+ }
+ log.info("{} API 응답 완료 (단건)", displayName);
+ return response;
+ }
+
+ protected List fetchPostList(Object body, Function uriFunction) {
+ log.info("{} API POST 호출", displayName);
+ List response = webClient.post()
+ .uri(uriFunction)
+ .body(BodyInserters.fromValue(body))
+ .retrieve()
+ .bodyToMono(listTypeRef)
+ .block();
+ if (response == null || response.isEmpty()) {
+ log.warn("{} API 응답 없음", displayName);
+ return List.of();
+ }
+ log.info("{} API 응답 완료 - 건수: {}", displayName, response.size());
+ return response;
+ }
+
+ protected T fetchPostOne(Object body, Function uriFunction) {
+ log.info("{} API POST 호출 (단건)", displayName);
+ T response = webClient.post()
+ .uri(uriFunction)
+ .body(BodyInserters.fromValue(body))
+ .retrieve()
+ .bodyToMono(singleTypeRef)
+ .block();
+ if (response == null) {
+ log.warn("{} API 응답 없음", displayName);
+ return null;
+ }
+ log.info("{} API 응답 완료 (단건)", displayName);
+ return response;
+ }
+
+ /**
+ * RAW GET 요청 → JsonNode 반환 (응답 구조 그대로 패스스루)
+ */
+ protected JsonNode fetchRawGet(Function uriFunction) {
+ log.info("{} API GET 호출 (RAW)", displayName);
+ JsonNode response = webClient.get()
+ .uri(uriFunction)
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .block();
+ log.info("{} API 응답 완료 (RAW)", displayName);
+ return response;
+ }
+
+ /**
+ * RAW POST 요청 → JsonNode 반환 (응답 구조 그대로 패스스루)
+ */
+ protected JsonNode fetchRawPost(Object body, Function uriFunction) {
+ log.info("{} API POST 호출 (RAW)", displayName);
+ JsonNode response = webClient.post()
+ .uri(uriFunction)
+ .body(BodyInserters.fromValue(body))
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .block();
+ log.info("{} API 응답 완료 (RAW)", displayName);
+ return response;
+ }
+
+ protected String getApiPath() {
+ return apiPath;
+ }
+
+ protected String getDisplayName() {
+ return displayName;
+ }
+}
diff --git a/src/main/java/com/snp/batch/global/config/SwaggerConfig.java b/src/main/java/com/snp/batch/global/config/SwaggerConfig.java
index 8cb1a22..40a5945 100644
--- a/src/main/java/com/snp/batch/global/config/SwaggerConfig.java
+++ b/src/main/java/com/snp/batch/global/config/SwaggerConfig.java
@@ -5,6 +5,7 @@ import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.servers.Server;
+import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -33,6 +34,39 @@ public class SwaggerConfig {
@Value("${server.servlet.context-path:}")
private String contextPath;
+ @Bean
+ public GroupedOpenApi batchManagementApi() {
+ return GroupedOpenApi.builder()
+ .group("1. Batch Management")
+ .pathsToMatch("/api/batch/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi bypassConfigApi() {
+ return GroupedOpenApi.builder()
+ .group("2. Bypass Config")
+ .pathsToMatch("/api/bypass-config/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi screeningGuideApi() {
+ return GroupedOpenApi.builder()
+ .group("4. Screening Guide")
+ .pathsToMatch("/api/screening-guide/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi bypassApi() {
+ return GroupedOpenApi.builder()
+ .group("3. Bypass API")
+ .pathsToMatch("/api/**")
+ .pathsToExclude("/api/batch/**", "/api/bypass-config/**", "/api/screening-guide/**")
+ .build();
+ }
+
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
@@ -41,21 +75,12 @@ public class SwaggerConfig {
new Server()
.url("http://localhost:" + serverPort + contextPath)
.description("로컬 개발 서버"),
- new Server()
- .url("http://10.26.252.39:" + serverPort + contextPath)
- .description("로컬 개발 서버"),
new Server()
.url("http://211.208.115.83:" + serverPort + contextPath)
.description("중계 서버"),
new Server()
.url("https://guide.gc-si.dev" + contextPath)
- .description("중계 서버 도메인"),
- new Server()
- .url("http://10.187.58.58:" + serverPort + contextPath)
- .description("운영 서버"),
- new Server()
- .url("https://mda.kcg.go.kr" + contextPath)
- .description("운영 서버 프록시")
+ .description("GC 도메인")
));
}
diff --git a/src/main/java/com/snp/batch/global/controller/BypassConfigController.java b/src/main/java/com/snp/batch/global/controller/BypassConfigController.java
new file mode 100644
index 0000000..28f648e
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/controller/BypassConfigController.java
@@ -0,0 +1,114 @@
+package com.snp.batch.global.controller;
+
+import com.snp.batch.common.web.ApiResponse;
+import com.snp.batch.global.dto.BypassConfigRequest;
+import com.snp.batch.global.dto.BypassConfigResponse;
+import com.snp.batch.global.dto.CodeGenerationResult;
+import com.snp.batch.global.model.BypassApiConfig;
+import com.snp.batch.global.repository.BypassApiConfigRepository;
+import com.snp.batch.service.BypassCodeGenerator;
+import com.snp.batch.service.BypassConfigService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * BYPASS API 설정 관리 및 코드 생성 컨트롤러
+ */
+@Slf4j
+@RestController
+@RequestMapping("/api/bypass-config")
+@RequiredArgsConstructor
+@Tag(name = "Bypass Config", description = "BYPASS API 설정 관리 및 코드 생성")
+public class BypassConfigController {
+
+ private final BypassConfigService bypassConfigService;
+ private final BypassCodeGenerator bypassCodeGenerator;
+ private final BypassApiConfigRepository configRepository;
+
+ @Operation(summary = "설정 목록 조회")
+ @GetMapping
+ public ResponseEntity>> getConfigs() {
+ return ResponseEntity.ok(ApiResponse.success(bypassConfigService.getConfigs()));
+ }
+
+ @Operation(summary = "설정 상세 조회")
+ @GetMapping("/{id}")
+ public ResponseEntity> getConfig(@PathVariable Long id) {
+ return ResponseEntity.ok(ApiResponse.success(bypassConfigService.getConfig(id)));
+ }
+
+ @Operation(summary = "설정 등록")
+ @PostMapping
+ public ResponseEntity> createConfig(
+ @RequestBody BypassConfigRequest request) {
+ return ResponseEntity.ok(ApiResponse.success(bypassConfigService.createConfig(request)));
+ }
+
+ @Operation(summary = "설정 수정")
+ @PutMapping("/{id}")
+ public ResponseEntity> updateConfig(
+ @PathVariable Long id,
+ @RequestBody BypassConfigRequest request) {
+ return ResponseEntity.ok(ApiResponse.success(bypassConfigService.updateConfig(id, request)));
+ }
+
+ @Operation(summary = "설정 삭제")
+ @DeleteMapping("/{id}")
+ public ResponseEntity> deleteConfig(@PathVariable Long id) {
+ bypassConfigService.deleteConfig(id);
+ return ResponseEntity.ok(ApiResponse.success("삭제 완료", null));
+ }
+
+ @Operation(
+ summary = "코드 생성",
+ description = "등록된 설정의 도메인 전체를 기반으로 Controller, Service 소스 코드를 생성합니다. 같은 도메인의 모든 설정을 하나의 Controller로 합칩니다."
+ )
+ @PostMapping("/{id}/generate")
+ public ResponseEntity> generateCode(
+ @PathVariable Long id,
+ @RequestParam(defaultValue = "false") boolean force) {
+ try {
+ BypassApiConfig config = configRepository.findById(id)
+ .orElseThrow(() -> new IllegalArgumentException("설정을 찾을 수 없습니다: " + id));
+
+ List domainConfigs = configRepository.findByDomainNameOrderById(config.getDomainName());
+
+ CodeGenerationResult result = bypassCodeGenerator.generate(domainConfigs, force);
+
+ domainConfigs.forEach(c -> bypassConfigService.markAsGenerated(c.getId()));
+
+ return ResponseEntity.ok(ApiResponse.success(result));
+ } catch (IllegalStateException e) {
+ return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
+ } catch (Exception e) {
+ log.error("코드 생성 실패", e);
+ return ResponseEntity.internalServerError().body(ApiResponse.error("코드 생성 실패: " + e.getMessage()));
+ }
+ }
+
+ @Operation(summary = "WebClient 빈 목록", description = "사용 가능한 WebClient 빈 이름 목록을 반환합니다.")
+ @GetMapping("/webclient-beans")
+ public ResponseEntity>>> getWebclientBeans() {
+ List> beans = List.of(
+ Map.of("name", "maritimeApiWebClient", "description", "Ship API (shipsapi.maritime.spglobal.com)"),
+ Map.of("name", "maritimeAisApiWebClient", "description", "AIS API (aisapi.maritime.spglobal.com)"),
+ Map.of("name", "maritimeServiceApiWebClient", "description", "Web Service API (webservices.maritime.spglobal.com)")
+ );
+ return ResponseEntity.ok(ApiResponse.success(beans));
+ }
+}
diff --git a/src/main/java/com/snp/batch/global/controller/ScreeningGuideController.java b/src/main/java/com/snp/batch/global/controller/ScreeningGuideController.java
new file mode 100644
index 0000000..df5d2b0
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/controller/ScreeningGuideController.java
@@ -0,0 +1,138 @@
+package com.snp.batch.global.controller;
+
+import com.snp.batch.common.web.ApiResponse;
+import com.snp.batch.global.dto.screening.ChangeHistoryResponse;
+import com.snp.batch.global.dto.screening.CompanyInfoResponse;
+import com.snp.batch.global.dto.screening.ComplianceCategoryResponse;
+import com.snp.batch.global.dto.screening.IndicatorStatusResponse;
+import com.snp.batch.global.dto.screening.MethodologyHistoryResponse;
+import com.snp.batch.global.dto.screening.RiskCategoryResponse;
+import com.snp.batch.global.dto.screening.ShipInfoResponse;
+import com.snp.batch.service.ScreeningGuideService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * Risk & Compliance Screening 가이드 조회 컨트롤러
+ */
+@Slf4j
+@RestController
+@RequestMapping("/api/screening-guide")
+@RequiredArgsConstructor
+@Tag(name = "Screening Guide", description = "Risk & Compliance Screening 가이드")
+public class ScreeningGuideController {
+
+ private final ScreeningGuideService screeningGuideService;
+
+ @Operation(summary = "Risk 지표 목록 조회", description = "카테고리별 Risk 지표 목록을 조회합니다.")
+ @GetMapping("/risk-indicators")
+ public ResponseEntity>> getRiskIndicators(
+ @Parameter(description = "언어 코드", example = "KO")
+ @RequestParam(defaultValue = "KO") String lang) {
+ return ResponseEntity.ok(ApiResponse.success(screeningGuideService.getRiskIndicators(lang)));
+ }
+
+ @Operation(summary = "Compliance 지표 목록 조회", description = "카테고리별 Compliance 지표 목록을 조회합니다.")
+ @GetMapping("/compliance-indicators")
+ public ResponseEntity>> getComplianceIndicators(
+ @Parameter(description = "언어 코드", example = "KO")
+ @RequestParam(defaultValue = "KO") String lang,
+ @Parameter(description = "지표 유형 (SHIP/COMPANY)", example = "SHIP")
+ @RequestParam(defaultValue = "SHIP") String type) {
+ return ResponseEntity.ok(ApiResponse.success(screeningGuideService.getComplianceIndicators(lang, type)));
+ }
+
+ @Operation(summary = "방법론 변경 이력 조회", description = "방법론 변경 이력을 조회합니다.")
+ @GetMapping("/methodology-history")
+ public ResponseEntity>> getMethodologyHistory(
+ @Parameter(description = "언어 코드", example = "KO")
+ @RequestParam(defaultValue = "KO") String lang) {
+ return ResponseEntity.ok(ApiResponse.success(screeningGuideService.getMethodologyHistory(lang)));
+ }
+
+ @Operation(summary = "선박 위험지표 값 변경 이력", description = "IMO 번호로 선박 위험지표 값 변경 이력을 조회합니다.")
+ @GetMapping("/history/ship-risk")
+ public ResponseEntity>> getShipRiskDetailHistory(
+ @Parameter(description = "IMO 번호", example = "9330019", required = true)
+ @RequestParam String imoNo,
+ @Parameter(description = "언어 코드", example = "KO")
+ @RequestParam(defaultValue = "KO") String lang) {
+ return ResponseEntity.ok(ApiResponse.success(screeningGuideService.getShipRiskDetailHistory(imoNo, lang)));
+ }
+
+ @Operation(summary = "선박 제재 값 변경 이력", description = "IMO 번호로 선박 제재 값 변경 이력을 조회합니다.")
+ @GetMapping("/history/ship-compliance")
+ public ResponseEntity>> getShipComplianceHistory(
+ @Parameter(description = "IMO 번호", example = "9330019", required = true)
+ @RequestParam String imoNo,
+ @Parameter(description = "언어 코드", example = "KO")
+ @RequestParam(defaultValue = "KO") String lang) {
+ return ResponseEntity.ok(ApiResponse.success(screeningGuideService.getShipComplianceHistory(imoNo, lang)));
+ }
+
+ @Operation(summary = "회사 제재 값 변경 이력", description = "회사 코드로 회사 제재 값 변경 이력을 조회합니다.")
+ @GetMapping("/history/company-compliance")
+ public ResponseEntity>> getCompanyComplianceHistory(
+ @Parameter(description = "회사 코드", example = "5765290", required = true)
+ @RequestParam String companyCode,
+ @Parameter(description = "언어 코드", example = "KO")
+ @RequestParam(defaultValue = "KO") String lang) {
+ return ResponseEntity.ok(ApiResponse.success(screeningGuideService.getCompanyComplianceHistory(companyCode, lang)));
+ }
+
+ @Operation(summary = "선박 기본 정보", description = "IMO 번호로 선박 기본 정보를 조회합니다.")
+ @GetMapping("/ship-info")
+ public ResponseEntity> getShipInfo(
+ @Parameter(description = "IMO 번호", example = "9672533", required = true)
+ @RequestParam String imoNo) {
+ return ResponseEntity.ok(ApiResponse.success(screeningGuideService.getShipInfo(imoNo)));
+ }
+
+ @Operation(summary = "선박 현재 Risk 지표 상태", description = "IMO 번호로 선박의 현재 Risk 지표 상태를 조회합니다.")
+ @GetMapping("/ship-risk-status")
+ public ResponseEntity>> getShipRiskStatus(
+ @Parameter(description = "IMO 번호", example = "9672533", required = true)
+ @RequestParam String imoNo,
+ @Parameter(description = "언어 코드", example = "KO")
+ @RequestParam(defaultValue = "KO") String lang) {
+ return ResponseEntity.ok(ApiResponse.success(screeningGuideService.getShipRiskStatus(imoNo, lang)));
+ }
+
+ @Operation(summary = "선박 현재 Compliance 상태", description = "IMO 번호로 선박의 현재 Compliance 상태를 조회합니다.")
+ @GetMapping("/ship-compliance-status")
+ public ResponseEntity>> getShipComplianceStatus(
+ @Parameter(description = "IMO 번호", example = "9672533", required = true)
+ @RequestParam String imoNo,
+ @Parameter(description = "언어 코드", example = "KO")
+ @RequestParam(defaultValue = "KO") String lang) {
+ return ResponseEntity.ok(ApiResponse.success(screeningGuideService.getShipComplianceStatus(imoNo, lang)));
+ }
+
+ @Operation(summary = "회사 기본 정보", description = "회사 코드로 회사 기본 정보를 조회합니다.")
+ @GetMapping("/company-info")
+ public ResponseEntity> getCompanyInfo(
+ @Parameter(description = "회사 코드", example = "1288896", required = true)
+ @RequestParam String companyCode) {
+ return ResponseEntity.ok(ApiResponse.success(screeningGuideService.getCompanyInfo(companyCode)));
+ }
+
+ @Operation(summary = "회사 현재 Compliance 상태", description = "회사 코드로 회사의 현재 Compliance 상태를 조회합니다.")
+ @GetMapping("/company-compliance-status")
+ public ResponseEntity>> getCompanyComplianceStatus(
+ @Parameter(description = "회사 코드", example = "1288896", required = true)
+ @RequestParam String companyCode,
+ @Parameter(description = "언어 코드", example = "KO")
+ @RequestParam(defaultValue = "KO") String lang) {
+ return ResponseEntity.ok(ApiResponse.success(screeningGuideService.getCompanyComplianceStatus(companyCode, lang)));
+ }
+}
diff --git a/src/main/java/com/snp/batch/global/controller/WebViewController.java b/src/main/java/com/snp/batch/global/controller/WebViewController.java
index 1c120c1..bf2206b 100644
--- a/src/main/java/com/snp/batch/global/controller/WebViewController.java
+++ b/src/main/java/com/snp/batch/global/controller/WebViewController.java
@@ -12,11 +12,13 @@ import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class WebViewController {
- @GetMapping({"/", "/jobs", "/executions", "/executions/{id:\\d+}",
+ @GetMapping({"/", "/dashboard", "/jobs", "/executions", "/executions/{id:\\d+}",
"/recollects", "/recollects/{id:\\d+}",
"/schedules", "/schedule-timeline", "/monitoring",
- "/jobs/**", "/executions/**", "/recollects/**",
- "/schedules/**", "/schedule-timeline/**", "/monitoring/**"})
+ "/bypass-config", "/screening-guide", "/risk-compliance-history",
+ "/dashboard/**", "/jobs/**", "/executions/**", "/recollects/**",
+ "/schedules/**", "/schedule-timeline/**", "/monitoring/**",
+ "/bypass-config/**", "/screening-guide/**", "/risk-compliance-history/**"})
public String forward() {
return "forward:/index.html";
}
diff --git a/src/main/java/com/snp/batch/global/dto/BypassConfigRequest.java b/src/main/java/com/snp/batch/global/dto/BypassConfigRequest.java
new file mode 100644
index 0000000..d008ecb
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/BypassConfigRequest.java
@@ -0,0 +1,39 @@
+package com.snp.batch.global.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * BYPASS API 설정 등록/수정 요청 DTO
+ */
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BypassConfigRequest {
+
+ /** 도메인명 (패키지명/URL 경로) */
+ private String domainName;
+
+ /** 표시명 */
+ private String displayName;
+
+ /** WebClient 빈 이름 */
+ private String webclientBean;
+
+ /** 외부 API 경로 */
+ private String externalPath;
+
+ /** HTTP 메서드 */
+ private String httpMethod;
+
+ /** 설명 */
+ private String description;
+
+ /** 파라미터 목록 */
+ private List params;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/BypassConfigResponse.java b/src/main/java/com/snp/batch/global/dto/BypassConfigResponse.java
new file mode 100644
index 0000000..a587260
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/BypassConfigResponse.java
@@ -0,0 +1,57 @@
+package com.snp.batch.global.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * BYPASS API 설정 조회 응답 DTO
+ */
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BypassConfigResponse {
+
+ private Long id;
+
+ /** 도메인명 (패키지명/URL 경로) */
+ private String domainName;
+
+ /** 엔드포인트명 (externalPath 마지막 세그먼트) */
+ private String endpointName;
+
+ /** 표시명 */
+ private String displayName;
+
+ /** WebClient 빈 이름 */
+ private String webclientBean;
+
+ /** 외부 API 경로 */
+ private String externalPath;
+
+ /** HTTP 메서드 */
+ private String httpMethod;
+
+ /** 설명 */
+ private String description;
+
+ /** 코드 생성 완료 여부 */
+ private Boolean generated;
+
+ /** 코드 생성 일시 */
+ private LocalDateTime generatedAt;
+
+ /** 생성 일시 */
+ private LocalDateTime createdAt;
+
+ /** 수정 일시 */
+ private LocalDateTime updatedAt;
+
+ /** 파라미터 목록 */
+ private List params;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/BypassParamDto.java b/src/main/java/com/snp/batch/global/dto/BypassParamDto.java
new file mode 100644
index 0000000..0885d12
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/BypassParamDto.java
@@ -0,0 +1,39 @@
+package com.snp.batch.global.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * BYPASS API 파라미터 정보 DTO
+ */
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BypassParamDto {
+
+ private Long id;
+
+ /** 파라미터 이름 */
+ private String paramName;
+
+ /** 파라미터 타입 (STRING, INTEGER, LONG, BOOLEAN) */
+ private String paramType;
+
+ /** 파라미터 위치 (PATH, QUERY, BODY) */
+ private String paramIn;
+
+ /** 필수 여부 */
+ private Boolean required;
+
+ /** 파라미터 설명 */
+ private String description;
+
+ /** 정렬 순서 */
+ private Integer sortOrder;
+
+ /** Swagger @Parameter example 값 */
+ private String example;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/CodeGenerationResult.java b/src/main/java/com/snp/batch/global/dto/CodeGenerationResult.java
new file mode 100644
index 0000000..d1ed597
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/CodeGenerationResult.java
@@ -0,0 +1,31 @@
+package com.snp.batch.global.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * 코드 자동 생성 결과 DTO
+ * 같은 도메인에 N개의 엔드포인트를 지원하므로 Service/DTO는 목록으로 반환
+ */
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CodeGenerationResult {
+
+ /** 생성된 Controller 파일 경로 */
+ private String controllerPath;
+
+ /** 생성된 Service 파일 경로 목록 (엔드포인트별) */
+ private List servicePaths;
+
+ /** 생성된 DTO 파일 경로 목록 (엔드포인트별) */
+ private List dtoPaths;
+
+ /** 결과 메시지 */
+ private String message;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/screening/ChangeHistoryResponse.java b/src/main/java/com/snp/batch/global/dto/screening/ChangeHistoryResponse.java
new file mode 100644
index 0000000..eb3e3fd
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/screening/ChangeHistoryResponse.java
@@ -0,0 +1,24 @@
+package com.snp.batch.global.dto.screening;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ChangeHistoryResponse {
+
+ private Long rowIndex;
+ private String searchKey;
+ private String lastModifiedDate;
+ private String changedColumnName;
+ private String beforeValue;
+ private String afterValue;
+ private String fieldName;
+ private String narrative;
+ private String prevNarrative;
+ private Integer sortOrder;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/screening/CompanyInfoResponse.java b/src/main/java/com/snp/batch/global/dto/screening/CompanyInfoResponse.java
new file mode 100644
index 0000000..1033d9a
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/screening/CompanyInfoResponse.java
@@ -0,0 +1,26 @@
+package com.snp.batch.global.dto.screening;
+
+import lombok.*;
+
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CompanyInfoResponse {
+ private String companyCode;
+ private String fullName;
+ private String abbreviation;
+ private String status;
+ private String parentCompanyCode;
+ private String parentCompanyName;
+ private String registrationCountry;
+ private String registrationCountryCode;
+ private String registrationCountryIsoCode;
+ private String controlCountry;
+ private String controlCountryCode;
+ private String controlCountryIsoCode;
+ private String foundedDate;
+ private String email;
+ private String phone;
+ private String website;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/screening/ComplianceCategoryResponse.java b/src/main/java/com/snp/batch/global/dto/screening/ComplianceCategoryResponse.java
new file mode 100644
index 0000000..26257ba
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/screening/ComplianceCategoryResponse.java
@@ -0,0 +1,19 @@
+package com.snp.batch.global.dto.screening;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ComplianceCategoryResponse {
+
+ private String category;
+ private String indicatorType;
+ private List indicators;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/screening/ComplianceIndicatorResponse.java b/src/main/java/com/snp/batch/global/dto/screening/ComplianceIndicatorResponse.java
new file mode 100644
index 0000000..43667fc
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/screening/ComplianceIndicatorResponse.java
@@ -0,0 +1,23 @@
+package com.snp.batch.global.dto.screening;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ComplianceIndicatorResponse {
+
+ private Integer indicatorId;
+ private String fieldKey;
+ private String fieldName;
+ private String description;
+ private String conditionRed;
+ private String conditionAmber;
+ private String conditionGreen;
+ private String dataType;
+ private String collectionNote;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/screening/IndicatorStatusResponse.java b/src/main/java/com/snp/batch/global/dto/screening/IndicatorStatusResponse.java
new file mode 100644
index 0000000..2fde664
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/screening/IndicatorStatusResponse.java
@@ -0,0 +1,16 @@
+package com.snp.batch.global.dto.screening;
+
+import lombok.*;
+
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IndicatorStatusResponse {
+ private String columnName;
+ private String fieldName;
+ private String category;
+ private String value;
+ private String narrative;
+ private Integer sortOrder;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/screening/MethodologyHistoryResponse.java b/src/main/java/com/snp/batch/global/dto/screening/MethodologyHistoryResponse.java
new file mode 100644
index 0000000..7849e88
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/screening/MethodologyHistoryResponse.java
@@ -0,0 +1,20 @@
+package com.snp.batch.global.dto.screening;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MethodologyHistoryResponse {
+
+ private Integer historyId;
+ private String changeDate;
+ private String changeType;
+ private String updateTitle;
+ private String description;
+ private String collectionNote;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/screening/RiskCategoryResponse.java b/src/main/java/com/snp/batch/global/dto/screening/RiskCategoryResponse.java
new file mode 100644
index 0000000..be9367f
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/screening/RiskCategoryResponse.java
@@ -0,0 +1,19 @@
+package com.snp.batch.global.dto.screening;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RiskCategoryResponse {
+
+ private String categoryCode;
+ private String categoryName;
+ private List indicators;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/screening/RiskIndicatorResponse.java b/src/main/java/com/snp/batch/global/dto/screening/RiskIndicatorResponse.java
new file mode 100644
index 0000000..14bae94
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/screening/RiskIndicatorResponse.java
@@ -0,0 +1,23 @@
+package com.snp.batch.global.dto.screening;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RiskIndicatorResponse {
+
+ private Integer indicatorId;
+ private String fieldKey;
+ private String fieldName;
+ private String description;
+ private String conditionRed;
+ private String conditionAmber;
+ private String conditionGreen;
+ private String dataType;
+ private String collectionNote;
+}
diff --git a/src/main/java/com/snp/batch/global/dto/screening/ShipInfoResponse.java b/src/main/java/com/snp/batch/global/dto/screening/ShipInfoResponse.java
new file mode 100644
index 0000000..b3c666d
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/dto/screening/ShipInfoResponse.java
@@ -0,0 +1,23 @@
+package com.snp.batch.global.dto.screening;
+
+import lombok.*;
+
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ShipInfoResponse {
+ private String imoNo;
+ private String shipName;
+ private String shipStatus;
+ private String nationalityCode;
+ private String nationalityIsoCode;
+ private String nationality;
+ private String shipType;
+ private String dwt;
+ private String gt;
+ private String buildYear;
+ private String mmsiNo;
+ private String callSign;
+ private String shipTypeGroup;
+}
diff --git a/src/main/java/com/snp/batch/global/model/BypassApiConfig.java b/src/main/java/com/snp/batch/global/model/BypassApiConfig.java
new file mode 100644
index 0000000..1c5b64d
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/BypassApiConfig.java
@@ -0,0 +1,153 @@
+package com.snp.batch.global.model;
+
+import jakarta.persistence.*;
+import lombok.*;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * BYPASS API 설정 정보를 저장하는 엔티티
+ * 외부 API를 동적으로 프록시하기 위한 설정 메타데이터
+ *
+ * JPA를 사용하므로 @PrePersist, @PreUpdate로 감사 필드 자동 설정
+ */
+@Entity
+@Table(name = "bypass_api_config",
+ uniqueConstraints = {
+ @UniqueConstraint(name = "uk_bypass_config_domain_endpoint", columnNames = {"domain_name", "endpoint_name"})
+ },
+ indexes = {
+ @Index(name = "idx_bypass_config_domain_name", columnList = "domain_name")
+ }
+)
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BypassApiConfig {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ /**
+ * 도메인명 (패키지명/URL 경로)
+ * 예: "ship-info", "port-data"
+ */
+ @Column(name = "domain_name", nullable = false, length = 50)
+ private String domainName;
+
+ /**
+ * 엔드포인트명 (externalPath의 마지막 세그먼트에서 자동 추출)
+ * 예: "CompliancesByImos", "CompanyCompliancesByImos"
+ */
+ @Column(name = "endpoint_name", nullable = false, length = 100)
+ private String endpointName;
+
+ /**
+ * 표시명
+ * 예: "선박 정보 API", "항만 데이터 API"
+ */
+ @Column(name = "display_name", nullable = false, length = 100)
+ private String displayName;
+
+ /**
+ * WebClient 빈 이름
+ * 예: "maritimeWebClient", "portWebClient"
+ */
+ @Column(name = "webclient_bean", nullable = false, length = 100)
+ private String webclientBean;
+
+ /**
+ * 외부 API 경로
+ * 예: "/api/v1/ships/{imoNumber}"
+ */
+ @Column(name = "external_path", nullable = false, length = 500)
+ private String externalPath;
+
+ /**
+ * HTTP 메서드
+ * 예: "GET", "POST"
+ */
+ @Column(name = "http_method", nullable = false, length = 10)
+ @Builder.Default
+ private String httpMethod = "GET";
+
+ /**
+ * 설명
+ */
+ @Column(name = "description", length = 1000)
+ private String description;
+
+ /**
+ * 코드 생성 완료 여부
+ */
+ @Column(name = "generated", nullable = false)
+ @Builder.Default
+ private Boolean generated = false;
+
+ /**
+ * 코드 생성 일시
+ */
+ @Column(name = "generated_at")
+ private LocalDateTime generatedAt;
+
+ /**
+ * 생성 일시 (감사 필드)
+ */
+ @Column(name = "created_at", nullable = false, updatable = false)
+ private LocalDateTime createdAt;
+
+ /**
+ * 수정 일시 (감사 필드)
+ */
+ @Column(name = "updated_at", nullable = false)
+ private LocalDateTime updatedAt;
+
+ /**
+ * API 파라미터 목록
+ */
+ @OneToMany(mappedBy = "config", cascade = CascadeType.ALL, orphanRemoval = true)
+ @Builder.Default
+ private List params = new ArrayList<>();
+
+ /**
+ * 엔티티 저장 전 자동 호출 (INSERT 시)
+ * endpointName이 null이면 externalPath에서 자동 추출 (마이그레이션 대응)
+ */
+ @PrePersist
+ protected void onCreate() {
+ LocalDateTime now = LocalDateTime.now();
+ this.createdAt = now;
+ this.updatedAt = now;
+ if (this.endpointName == null || this.endpointName.isEmpty()) {
+ this.endpointName = extractEndpointName(this.externalPath);
+ }
+ }
+
+ /**
+ * 엔티티 업데이트 전 자동 호출 (UPDATE 시)
+ * endpointName이 null이면 externalPath에서 자동 추출 (마이그레이션 대응)
+ */
+ private static String extractEndpointName(String externalPath) {
+ if (externalPath == null || externalPath.isEmpty()) {
+ return "";
+ }
+ String[] segments = externalPath.split("/");
+ return segments[segments.length - 1];
+ }
+
+ /**
+ * 엔티티 업데이트 전 자동 호출 (UPDATE 시)
+ */
+ @PreUpdate
+ protected void onUpdate() {
+ this.updatedAt = LocalDateTime.now();
+ if (this.endpointName == null || this.endpointName.isEmpty()) {
+ this.endpointName = extractEndpointName(this.externalPath);
+ }
+ }
+}
diff --git a/src/main/java/com/snp/batch/global/model/BypassApiParam.java b/src/main/java/com/snp/batch/global/model/BypassApiParam.java
new file mode 100644
index 0000000..a86288c
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/BypassApiParam.java
@@ -0,0 +1,83 @@
+package com.snp.batch.global.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.*;
+import lombok.*;
+
+/**
+ * BYPASS API 파라미터 정보를 저장하는 엔티티
+ * BypassApiConfig에 종속되며, API 호출 시 사용할 파라미터 메타데이터를 정의
+ */
+@Entity
+@Table(
+ name = "bypass_api_param",
+ uniqueConstraints = @UniqueConstraint(columnNames = {"config_id", "param_name"})
+)
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BypassApiParam {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ /**
+ * 연관된 BYPASS API 설정
+ */
+ @JsonIgnore
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "config_id", nullable = false)
+ private BypassApiConfig config;
+
+ /**
+ * 파라미터 이름
+ * 예: "imoNumber", "mmsi", "startDate"
+ */
+ @Column(name = "param_name", nullable = false, length = 100)
+ private String paramName;
+
+ /**
+ * 파라미터 타입
+ * 예: "STRING", "INTEGER", "LONG", "BOOLEAN"
+ */
+ @Column(name = "param_type", nullable = false, length = 20)
+ @Builder.Default
+ private String paramType = "STRING";
+
+ /**
+ * 파라미터 위치
+ * 예: "PATH", "QUERY", "BODY"
+ */
+ @Column(name = "param_in", nullable = false, length = 20)
+ @Builder.Default
+ private String paramIn = "QUERY";
+
+ /**
+ * 필수 여부
+ */
+ @Column(name = "required", nullable = false)
+ @Builder.Default
+ private Boolean required = true;
+
+ /**
+ * 파라미터 설명
+ */
+ @Column(name = "description", length = 500)
+ private String description;
+
+ /**
+ * 정렬 순서
+ */
+ @Column(name = "sort_order", nullable = false)
+ @Builder.Default
+ private Integer sortOrder = 0;
+
+ /**
+ * Swagger @Parameter example 값
+ */
+ @Column(name = "example", length = 200)
+ private String example;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/ChangeType.java b/src/main/java/com/snp/batch/global/model/screening/ChangeType.java
new file mode 100644
index 0000000..4441313
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/ChangeType.java
@@ -0,0 +1,25 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 방법론 변경 유형 코드 마스터 엔티티 (읽기 전용)
+ */
+@Entity
+@Table(name = "change_type", schema = "std_snp_data")
+@Getter
+@NoArgsConstructor
+public class ChangeType {
+
+ @Id
+ @Column(name = "type_code", length = 30)
+ private String typeCode;
+
+ @Column(name = "sort_order", nullable = false)
+ private Integer sortOrder;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/ChangeTypeLang.java b/src/main/java/com/snp/batch/global/model/screening/ChangeTypeLang.java
new file mode 100644
index 0000000..062a284
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/ChangeTypeLang.java
@@ -0,0 +1,31 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.IdClass;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 방법론 변경 유형 다국어 엔티티 (읽기 전용)
+ */
+@Entity
+@Table(name = "change_type_lang", schema = "std_snp_data")
+@IdClass(ChangeTypeLangId.class)
+@Getter
+@NoArgsConstructor
+public class ChangeTypeLang {
+
+ @Id
+ @Column(name = "type_code", length = 30)
+ private String typeCode;
+
+ @Id
+ @Column(name = "lang_code", length = 5)
+ private String langCode;
+
+ @Column(name = "type_name", nullable = false, length = 100)
+ private String typeName;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/ChangeTypeLangId.java b/src/main/java/com/snp/batch/global/model/screening/ChangeTypeLangId.java
new file mode 100644
index 0000000..7a86247
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/ChangeTypeLangId.java
@@ -0,0 +1,33 @@
+package com.snp.batch.global.model.screening;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * 방법론 변경 유형 다국어 복합 PK
+ */
+public class ChangeTypeLangId implements Serializable {
+
+ private String typeCode;
+ private String langCode;
+
+ public ChangeTypeLangId() {
+ }
+
+ public ChangeTypeLangId(String typeCode, String langCode) {
+ this.typeCode = typeCode;
+ this.langCode = langCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ChangeTypeLangId that)) return false;
+ return Objects.equals(typeCode, that.typeCode) && Objects.equals(langCode, that.langCode);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(typeCode, langCode);
+ }
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/CompanyComplianceHistory.java b/src/main/java/com/snp/batch/global/model/screening/CompanyComplianceHistory.java
new file mode 100644
index 0000000..2d56843
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/CompanyComplianceHistory.java
@@ -0,0 +1,45 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * 회사 제재 값 변경 이력 (읽기 전용)
+ */
+@Entity
+@Table(name = "tb_company_compliance_info_hstry", schema = "std_snp_svc")
+@Getter
+@NoArgsConstructor
+public class CompanyComplianceHistory {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "row_index")
+ private Long rowIndex;
+
+ @Column(name = "company_cd", nullable = false, length = 14)
+ private String companyCode;
+
+ @Column(name = "last_mdfcn_dt", nullable = false)
+ private LocalDateTime lastModifiedDate;
+
+ @Column(name = "flctn_col_nm", nullable = false, length = 100)
+ private String changedColumnName;
+
+ @Column(name = "bfr_val", length = 4)
+ private String beforeValue;
+
+ @Column(name = "aftr_val", length = 4)
+ private String afterValue;
+
+ @Column(name = "crt_dt", nullable = false)
+ private LocalDateTime createdDate;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/CompanyDetailInfo.java b/src/main/java/com/snp/batch/global/model/screening/CompanyDetailInfo.java
new file mode 100644
index 0000000..2d52875
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/CompanyDetailInfo.java
@@ -0,0 +1,61 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Entity
+@Table(name = "tb_company_dtl_info", schema = "std_snp_svc")
+@Getter
+@NoArgsConstructor
+public class CompanyDetailInfo {
+
+ @Id
+ @Column(name = "company_cd", length = 14)
+ private String companyCode;
+
+ @Column(name = "full_nm", length = 280)
+ private String fullName;
+
+ @Column(name = "company_name_abbr", length = 60)
+ private String abbreviation;
+
+ @Column(name = "country_nm", length = 40)
+ private String country;
+
+ @Column(name = "cty_nm", length = 200)
+ private String city;
+
+ @Column(name = "company_status", length = 8)
+ private String status;
+
+ @Column(name = "country_reg", length = 40)
+ private String registrationCountry;
+
+ @Column(name = "oa_addr", length = 512)
+ private String address;
+
+ @Column(name = "prnt_company_cd", length = 14)
+ private String parentCompanyCode;
+
+ @Column(name = "country_reg_cd", length = 6)
+ private String registrationCountryCode;
+
+ @Column(name = "country_ctrl", length = 40)
+ private String controlCountry;
+
+ @Column(name = "country_ctrl_cd", length = 6)
+ private String controlCountryCode;
+
+ @Column(name = "company_fndn_ymd", length = 8)
+ private String foundedDate;
+
+ @Column(name = "eml_addr", length = 320)
+ private String email;
+
+ @Column(name = "tel", length = 60)
+ private String phone;
+
+ @Column(name = "wbst_url", length = 120)
+ private String website;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/ComplianceIndicator.java b/src/main/java/com/snp/batch/global/model/screening/ComplianceIndicator.java
new file mode 100644
index 0000000..6211b3b
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/ComplianceIndicator.java
@@ -0,0 +1,47 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 컴플라이언스 지표 마스터 엔티티 (읽기 전용)
+ * indicator_type: SHIP 또는 COMPANY
+ */
+@Entity
+@Table(name = "compliance_indicator", schema = "std_snp_data")
+@Getter
+@NoArgsConstructor
+public class ComplianceIndicator {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "indicator_id")
+ private Integer indicatorId;
+
+ @Column(name = "indicator_type", nullable = false, length = 20)
+ private String indicatorType;
+
+ @Column(name = "category", nullable = false, length = 100)
+ private String category;
+
+ @Column(name = "field_key", nullable = false, length = 200)
+ private String fieldKey;
+
+ @Column(name = "data_type_code", length = 50)
+ private String dataTypeCode;
+
+ @Column(name = "collection_note", columnDefinition = "TEXT")
+ private String collectionNote;
+
+ @Column(name = "sort_order", nullable = false)
+ private Integer sortOrder;
+
+ @Column(name = "column_name", length = 100)
+ private String columnName;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/ComplianceIndicatorLang.java b/src/main/java/com/snp/batch/global/model/screening/ComplianceIndicatorLang.java
new file mode 100644
index 0000000..aca1776
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/ComplianceIndicatorLang.java
@@ -0,0 +1,43 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.IdClass;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 컴플라이언스 지표 다국어 번역 엔티티 (읽기 전용)
+ */
+@Entity
+@Table(name = "compliance_indicator_lang", schema = "std_snp_data")
+@IdClass(ComplianceIndicatorLangId.class)
+@Getter
+@NoArgsConstructor
+public class ComplianceIndicatorLang {
+
+ @Id
+ @Column(name = "indicator_id")
+ private Integer indicatorId;
+
+ @Id
+ @Column(name = "lang_code", length = 5)
+ private String langCode;
+
+ @Column(name = "field_name", nullable = false, length = 500)
+ private String fieldName;
+
+ @Column(name = "description", columnDefinition = "TEXT")
+ private String description;
+
+ @Column(name = "condition_red", length = 500)
+ private String conditionRed;
+
+ @Column(name = "condition_amber", length = 500)
+ private String conditionAmber;
+
+ @Column(name = "condition_green", length = 500)
+ private String conditionGreen;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/ComplianceIndicatorLangId.java b/src/main/java/com/snp/batch/global/model/screening/ComplianceIndicatorLangId.java
new file mode 100644
index 0000000..012170d
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/ComplianceIndicatorLangId.java
@@ -0,0 +1,33 @@
+package com.snp.batch.global.model.screening;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * 컴플라이언스 지표 다국어 복합 PK
+ */
+public class ComplianceIndicatorLangId implements Serializable {
+
+ private Integer indicatorId;
+ private String langCode;
+
+ public ComplianceIndicatorLangId() {
+ }
+
+ public ComplianceIndicatorLangId(Integer indicatorId, String langCode) {
+ this.indicatorId = indicatorId;
+ this.langCode = langCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ComplianceIndicatorLangId that)) return false;
+ return Objects.equals(indicatorId, that.indicatorId) && Objects.equals(langCode, that.langCode);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(indicatorId, langCode);
+ }
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/Language.java b/src/main/java/com/snp/batch/global/model/screening/Language.java
new file mode 100644
index 0000000..c75d73e
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/Language.java
@@ -0,0 +1,28 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 다국어 언어 코드 메타 엔티티 (읽기 전용)
+ */
+@Entity
+@Table(name = "language", schema = "std_snp_data")
+@Getter
+@NoArgsConstructor
+public class Language {
+
+ @Id
+ @Column(name = "lang_code", length = 5)
+ private String langCode;
+
+ @Column(name = "lang_name", nullable = false, length = 50)
+ private String langName;
+
+ @Column(name = "is_active", nullable = false)
+ private Boolean isActive;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/MethodologyHistory.java b/src/main/java/com/snp/batch/global/model/screening/MethodologyHistory.java
new file mode 100644
index 0000000..8d51265
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/MethodologyHistory.java
@@ -0,0 +1,39 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDate;
+
+/**
+ * 방법론 변경 이력 마스터 엔티티 (읽기 전용)
+ */
+@Entity
+@Table(name = "methodology_history", schema = "std_snp_data")
+@Getter
+@NoArgsConstructor
+public class MethodologyHistory {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "history_id")
+ private Integer historyId;
+
+ @Column(name = "change_date", nullable = false)
+ private LocalDate changeDate;
+
+ @Column(name = "change_type_code", nullable = false, length = 30)
+ private String changeTypeCode;
+
+ @Column(name = "collection_note", columnDefinition = "TEXT")
+ private String collectionNote;
+
+ @Column(name = "sort_order", nullable = false)
+ private Integer sortOrder;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/MethodologyHistoryLang.java b/src/main/java/com/snp/batch/global/model/screening/MethodologyHistoryLang.java
new file mode 100644
index 0000000..08d77e3
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/MethodologyHistoryLang.java
@@ -0,0 +1,34 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.IdClass;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 방법론 변경 이력 다국어 번역 엔티티 (읽기 전용)
+ */
+@Entity
+@Table(name = "methodology_history_lang", schema = "std_snp_data")
+@IdClass(MethodologyHistoryLangId.class)
+@Getter
+@NoArgsConstructor
+public class MethodologyHistoryLang {
+
+ @Id
+ @Column(name = "history_id")
+ private Integer historyId;
+
+ @Id
+ @Column(name = "lang_code", length = 5)
+ private String langCode;
+
+ @Column(name = "update_title", length = 500)
+ private String updateTitle;
+
+ @Column(name = "description", columnDefinition = "TEXT")
+ private String description;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/MethodologyHistoryLangId.java b/src/main/java/com/snp/batch/global/model/screening/MethodologyHistoryLangId.java
new file mode 100644
index 0000000..0604186
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/MethodologyHistoryLangId.java
@@ -0,0 +1,33 @@
+package com.snp.batch.global.model.screening;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * 방법론 변경 이력 다국어 복합 PK
+ */
+public class MethodologyHistoryLangId implements Serializable {
+
+ private Integer historyId;
+ private String langCode;
+
+ public MethodologyHistoryLangId() {
+ }
+
+ public MethodologyHistoryLangId(Integer historyId, String langCode) {
+ this.historyId = historyId;
+ this.langCode = langCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MethodologyHistoryLangId that)) return false;
+ return Objects.equals(historyId, that.historyId) && Objects.equals(langCode, that.langCode);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(historyId, langCode);
+ }
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/RiskIndicator.java b/src/main/java/com/snp/batch/global/model/screening/RiskIndicator.java
new file mode 100644
index 0000000..374ab01
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/RiskIndicator.java
@@ -0,0 +1,43 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 위험 지표 마스터 엔티티 (읽기 전용)
+ */
+@Entity
+@Table(name = "risk_indicator", schema = "std_snp_data")
+@Getter
+@NoArgsConstructor
+public class RiskIndicator {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "indicator_id")
+ private Integer indicatorId;
+
+ @Column(name = "category_code", nullable = false, length = 50)
+ private String categoryCode;
+
+ @Column(name = "field_key", nullable = false, length = 200)
+ private String fieldKey;
+
+ @Column(name = "data_type_code", length = 50)
+ private String dataTypeCode;
+
+ @Column(name = "collection_note", columnDefinition = "TEXT")
+ private String collectionNote;
+
+ @Column(name = "sort_order", nullable = false)
+ private Integer sortOrder;
+
+ @Column(name = "column_name", length = 100)
+ private String columnName;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorCategory.java b/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorCategory.java
new file mode 100644
index 0000000..5f3b6bd
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorCategory.java
@@ -0,0 +1,25 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 위험 지표 카테고리 마스터 엔티티 (읽기 전용)
+ */
+@Entity
+@Table(name = "risk_indicator_category", schema = "std_snp_data")
+@Getter
+@NoArgsConstructor
+public class RiskIndicatorCategory {
+
+ @Id
+ @Column(name = "category_code", length = 50)
+ private String categoryCode;
+
+ @Column(name = "sort_order", nullable = false)
+ private Integer sortOrder;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorCategoryLang.java b/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorCategoryLang.java
new file mode 100644
index 0000000..88ffd3d
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorCategoryLang.java
@@ -0,0 +1,31 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.IdClass;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 위험 지표 카테고리 다국어 엔티티 (읽기 전용)
+ */
+@Entity
+@Table(name = "risk_indicator_category_lang", schema = "std_snp_data")
+@IdClass(RiskIndicatorCategoryLangId.class)
+@Getter
+@NoArgsConstructor
+public class RiskIndicatorCategoryLang {
+
+ @Id
+ @Column(name = "category_code", length = 50)
+ private String categoryCode;
+
+ @Id
+ @Column(name = "lang_code", length = 5)
+ private String langCode;
+
+ @Column(name = "category_name", nullable = false, length = 200)
+ private String categoryName;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorCategoryLangId.java b/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorCategoryLangId.java
new file mode 100644
index 0000000..d85d61b
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorCategoryLangId.java
@@ -0,0 +1,33 @@
+package com.snp.batch.global.model.screening;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * 위험 지표 카테고리 다국어 복합 PK
+ */
+public class RiskIndicatorCategoryLangId implements Serializable {
+
+ private String categoryCode;
+ private String langCode;
+
+ public RiskIndicatorCategoryLangId() {
+ }
+
+ public RiskIndicatorCategoryLangId(String categoryCode, String langCode) {
+ this.categoryCode = categoryCode;
+ this.langCode = langCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof RiskIndicatorCategoryLangId that)) return false;
+ return Objects.equals(categoryCode, that.categoryCode) && Objects.equals(langCode, that.langCode);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(categoryCode, langCode);
+ }
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorLang.java b/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorLang.java
new file mode 100644
index 0000000..3932943
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorLang.java
@@ -0,0 +1,43 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.IdClass;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 위험 지표 다국어 번역 엔티티 (읽기 전용)
+ */
+@Entity
+@Table(name = "risk_indicator_lang", schema = "std_snp_data")
+@IdClass(RiskIndicatorLangId.class)
+@Getter
+@NoArgsConstructor
+public class RiskIndicatorLang {
+
+ @Id
+ @Column(name = "indicator_id")
+ private Integer indicatorId;
+
+ @Id
+ @Column(name = "lang_code", length = 5)
+ private String langCode;
+
+ @Column(name = "field_name", nullable = false, length = 500)
+ private String fieldName;
+
+ @Column(name = "description", columnDefinition = "TEXT")
+ private String description;
+
+ @Column(name = "condition_red", length = 500)
+ private String conditionRed;
+
+ @Column(name = "condition_amber", length = 500)
+ private String conditionAmber;
+
+ @Column(name = "condition_green", length = 500)
+ private String conditionGreen;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorLangId.java b/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorLangId.java
new file mode 100644
index 0000000..5149130
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/RiskIndicatorLangId.java
@@ -0,0 +1,33 @@
+package com.snp.batch.global.model.screening;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * 위험 지표 다국어 복합 PK
+ */
+public class RiskIndicatorLangId implements Serializable {
+
+ private Integer indicatorId;
+ private String langCode;
+
+ public RiskIndicatorLangId() {
+ }
+
+ public RiskIndicatorLangId(Integer indicatorId, String langCode) {
+ this.indicatorId = indicatorId;
+ this.langCode = langCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof RiskIndicatorLangId that)) return false;
+ return Objects.equals(indicatorId, that.indicatorId) && Objects.equals(langCode, that.langCode);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(indicatorId, langCode);
+ }
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/ShipComplianceHistory.java b/src/main/java/com/snp/batch/global/model/screening/ShipComplianceHistory.java
new file mode 100644
index 0000000..0d0f13c
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/ShipComplianceHistory.java
@@ -0,0 +1,45 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * 선박 제재 값 변경 이력 (읽기 전용)
+ */
+@Entity
+@Table(name = "tb_ship_compliance_info_hstry", schema = "std_snp_svc")
+@Getter
+@NoArgsConstructor
+public class ShipComplianceHistory {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "row_index")
+ private Long rowIndex;
+
+ @Column(name = "imo_no", nullable = false, length = 10)
+ private String imoNo;
+
+ @Column(name = "last_mdfcn_dt", nullable = false)
+ private LocalDateTime lastModifiedDate;
+
+ @Column(name = "flctn_col_nm", nullable = false, length = 100)
+ private String changedColumnName;
+
+ @Column(name = "bfr_val", length = 4)
+ private String beforeValue;
+
+ @Column(name = "aftr_val", length = 4)
+ private String afterValue;
+
+ @Column(name = "crt_dt", nullable = false)
+ private LocalDateTime createdDate;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/ShipCountryCode.java b/src/main/java/com/snp/batch/global/model/screening/ShipCountryCode.java
new file mode 100644
index 0000000..dcd7df9
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/ShipCountryCode.java
@@ -0,0 +1,25 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Entity
+@Table(name = "tb_ship_country_cd", schema = "std_snp_svc")
+@Getter
+@NoArgsConstructor
+public class ShipCountryCode {
+
+ @Id
+ @Column(name = "ship_country_cd", length = 3)
+ private String shipCountryCode;
+
+ @Column(name = "cd_nm", length = 100)
+ private String codeName;
+
+ @Column(name = "iso_two_cd", length = 2)
+ private String isoTwoCode;
+
+ @Column(name = "iso_thr_cd", length = 3)
+ private String isoThreeCode;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/ShipInfoMaster.java b/src/main/java/com/snp/batch/global/model/screening/ShipInfoMaster.java
new file mode 100644
index 0000000..4fb9950
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/ShipInfoMaster.java
@@ -0,0 +1,49 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Entity
+@Table(name = "tb_ship_info_mst", schema = "std_snp_svc")
+@Getter
+@NoArgsConstructor
+public class ShipInfoMaster {
+
+ @Id
+ @Column(name = "imo_no", length = 10)
+ private String imoNo;
+
+ @Column(name = "ship_nm", length = 75)
+ private String shipName;
+
+ @Column(name = "ship_status", length = 50)
+ private String shipStatus;
+
+ @Column(name = "ntnlty_cd", length = 50)
+ private String nationalityCode;
+
+ @Column(name = "ship_ntnlty", length = 57)
+ private String nationality;
+
+ @Column(name = "ship_type_lv_five", length = 73)
+ private String shipType;
+
+ @Column(name = "dwt", length = 50)
+ private String dwt;
+
+ @Column(name = "gt", length = 50)
+ private String gt;
+
+ @Column(name = "build_yy", length = 50)
+ private String buildYear;
+
+ @Column(name = "mmsi_no", length = 50)
+ private String mmsiNo;
+
+ @Column(name = "clsgn_no", length = 50)
+ private String callSign;
+
+ @Column(name = "ship_type_lv_two", length = 50)
+ private String shipTypeGroup;
+}
diff --git a/src/main/java/com/snp/batch/global/model/screening/ShipRiskDetailHistory.java b/src/main/java/com/snp/batch/global/model/screening/ShipRiskDetailHistory.java
new file mode 100644
index 0000000..03f0fd0
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/model/screening/ShipRiskDetailHistory.java
@@ -0,0 +1,45 @@
+package com.snp.batch.global.model.screening;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * 선박 위험지표 값 변경 이력 (읽기 전용)
+ */
+@Entity
+@Table(name = "tb_ship_risk_detail_info_hstry", schema = "std_snp_svc")
+@Getter
+@NoArgsConstructor
+public class ShipRiskDetailHistory {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "row_index")
+ private Long rowIndex;
+
+ @Column(name = "imo_no", nullable = false, length = 10)
+ private String imoNo;
+
+ @Column(name = "last_mdfcn_dt", nullable = false)
+ private LocalDateTime lastModifiedDate;
+
+ @Column(name = "flctn_col_nm", nullable = false, length = 100)
+ private String changedColumnName;
+
+ @Column(name = "bfr_val", length = 4)
+ private String beforeValue;
+
+ @Column(name = "aftr_val", length = 4)
+ private String afterValue;
+
+ @Column(name = "crt_dt", nullable = false)
+ private LocalDateTime createdDate;
+}
diff --git a/src/main/java/com/snp/batch/global/repository/BypassApiConfigRepository.java b/src/main/java/com/snp/batch/global/repository/BypassApiConfigRepository.java
new file mode 100644
index 0000000..1f19563
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/BypassApiConfigRepository.java
@@ -0,0 +1,31 @@
+package com.snp.batch.global.repository;
+
+import com.snp.batch.global.model.BypassApiConfig;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * BypassApiConfig Repository
+ * JPA Repository 방식으로 자동 구현
+ */
+@Repository
+public interface BypassApiConfigRepository extends JpaRepository {
+
+ /**
+ * 도메인명으로 BYPASS API 설정 단건 조회 (하위 호환)
+ */
+ Optional findByDomainName(String domainName);
+
+ /**
+ * 도메인명으로 BYPASS API 설정 목록 조회 (ID 순)
+ */
+ List findByDomainNameOrderById(String domainName);
+
+ /**
+ * 도메인명 + 엔드포인트명 복합 유니크 존재 여부 확인
+ */
+ boolean existsByDomainNameAndEndpointName(String domainName, String endpointName);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/BypassApiParamRepository.java b/src/main/java/com/snp/batch/global/repository/BypassApiParamRepository.java
new file mode 100644
index 0000000..cff846e
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/BypassApiParamRepository.java
@@ -0,0 +1,25 @@
+package com.snp.batch.global.repository;
+
+import com.snp.batch.global.model.BypassApiParam;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * BypassApiParam Repository
+ * JPA Repository 방식으로 자동 구현
+ */
+@Repository
+public interface BypassApiParamRepository extends JpaRepository {
+
+ /**
+ * 설정 ID로 파라미터 목록 조회 (정렬 순서 기준 오름차순)
+ */
+ List findByConfigIdOrderBySortOrder(Long configId);
+
+ /**
+ * 설정 ID로 파라미터 전체 삭제
+ */
+ void deleteByConfigId(Long configId);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/ChangeTypeLangRepository.java b/src/main/java/com/snp/batch/global/repository/screening/ChangeTypeLangRepository.java
new file mode 100644
index 0000000..7571a20
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/ChangeTypeLangRepository.java
@@ -0,0 +1,14 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.ChangeTypeLang;
+import com.snp.batch.global.model.screening.ChangeTypeLangId;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ChangeTypeLangRepository extends JpaRepository {
+
+ List findByLangCode(String langCode);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/CompanyComplianceHistoryRepository.java b/src/main/java/com/snp/batch/global/repository/screening/CompanyComplianceHistoryRepository.java
new file mode 100644
index 0000000..522062f
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/CompanyComplianceHistoryRepository.java
@@ -0,0 +1,12 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.CompanyComplianceHistory;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface CompanyComplianceHistoryRepository extends JpaRepository {
+ List findByCompanyCodeOrderByLastModifiedDateDesc(String companyCode);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/CompanyDetailInfoRepository.java b/src/main/java/com/snp/batch/global/repository/screening/CompanyDetailInfoRepository.java
new file mode 100644
index 0000000..5d62004
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/CompanyDetailInfoRepository.java
@@ -0,0 +1,12 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.CompanyDetailInfo;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface CompanyDetailInfoRepository extends JpaRepository {
+ Optional findByCompanyCode(String companyCode);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/ComplianceIndicatorLangRepository.java b/src/main/java/com/snp/batch/global/repository/screening/ComplianceIndicatorLangRepository.java
new file mode 100644
index 0000000..a68762a
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/ComplianceIndicatorLangRepository.java
@@ -0,0 +1,14 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.ComplianceIndicatorLang;
+import com.snp.batch.global.model.screening.ComplianceIndicatorLangId;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ComplianceIndicatorLangRepository extends JpaRepository {
+
+ List findByLangCode(String langCode);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/ComplianceIndicatorRepository.java b/src/main/java/com/snp/batch/global/repository/screening/ComplianceIndicatorRepository.java
new file mode 100644
index 0000000..d738c66
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/ComplianceIndicatorRepository.java
@@ -0,0 +1,15 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.ComplianceIndicator;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ComplianceIndicatorRepository extends JpaRepository {
+
+ List findByIndicatorTypeOrderBySortOrderAsc(String indicatorType);
+
+ List findAllByOrderBySortOrderAsc();
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/MethodologyHistoryLangRepository.java b/src/main/java/com/snp/batch/global/repository/screening/MethodologyHistoryLangRepository.java
new file mode 100644
index 0000000..e75fb98
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/MethodologyHistoryLangRepository.java
@@ -0,0 +1,14 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.MethodologyHistoryLang;
+import com.snp.batch.global.model.screening.MethodologyHistoryLangId;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface MethodologyHistoryLangRepository extends JpaRepository {
+
+ List findByLangCode(String langCode);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/MethodologyHistoryRepository.java b/src/main/java/com/snp/batch/global/repository/screening/MethodologyHistoryRepository.java
new file mode 100644
index 0000000..e21990a
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/MethodologyHistoryRepository.java
@@ -0,0 +1,13 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.MethodologyHistory;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface MethodologyHistoryRepository extends JpaRepository {
+
+ List findAllByOrderByChangeDateDescSortOrderAsc();
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/RiskIndicatorCategoryLangRepository.java b/src/main/java/com/snp/batch/global/repository/screening/RiskIndicatorCategoryLangRepository.java
new file mode 100644
index 0000000..eb0dfe7
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/RiskIndicatorCategoryLangRepository.java
@@ -0,0 +1,14 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.RiskIndicatorCategoryLang;
+import com.snp.batch.global.model.screening.RiskIndicatorCategoryLangId;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface RiskIndicatorCategoryLangRepository extends JpaRepository {
+
+ List findByLangCode(String langCode);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/RiskIndicatorLangRepository.java b/src/main/java/com/snp/batch/global/repository/screening/RiskIndicatorLangRepository.java
new file mode 100644
index 0000000..3c728c4
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/RiskIndicatorLangRepository.java
@@ -0,0 +1,14 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.RiskIndicatorLang;
+import com.snp.batch.global.model.screening.RiskIndicatorLangId;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface RiskIndicatorLangRepository extends JpaRepository {
+
+ List findByLangCodeOrderByIndicatorIdAsc(String langCode);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/RiskIndicatorRepository.java b/src/main/java/com/snp/batch/global/repository/screening/RiskIndicatorRepository.java
new file mode 100644
index 0000000..b5d8fcc
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/RiskIndicatorRepository.java
@@ -0,0 +1,13 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.RiskIndicator;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface RiskIndicatorRepository extends JpaRepository {
+
+ List findAllByOrderByCategoryCodeAscSortOrderAsc();
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/ShipComplianceHistoryRepository.java b/src/main/java/com/snp/batch/global/repository/screening/ShipComplianceHistoryRepository.java
new file mode 100644
index 0000000..d64adbf
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/ShipComplianceHistoryRepository.java
@@ -0,0 +1,12 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.ShipComplianceHistory;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ShipComplianceHistoryRepository extends JpaRepository {
+ List findByImoNoOrderByLastModifiedDateDesc(String imoNo);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/ShipCountryCodeRepository.java b/src/main/java/com/snp/batch/global/repository/screening/ShipCountryCodeRepository.java
new file mode 100644
index 0000000..7d48f7e
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/ShipCountryCodeRepository.java
@@ -0,0 +1,12 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.ShipCountryCode;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface ShipCountryCodeRepository extends JpaRepository {
+ Optional findByShipCountryCode(String shipCountryCode);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/ShipInfoMasterRepository.java b/src/main/java/com/snp/batch/global/repository/screening/ShipInfoMasterRepository.java
new file mode 100644
index 0000000..12cb0f0
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/ShipInfoMasterRepository.java
@@ -0,0 +1,12 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.ShipInfoMaster;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface ShipInfoMasterRepository extends JpaRepository {
+ Optional findByImoNo(String imoNo);
+}
diff --git a/src/main/java/com/snp/batch/global/repository/screening/ShipRiskDetailHistoryRepository.java b/src/main/java/com/snp/batch/global/repository/screening/ShipRiskDetailHistoryRepository.java
new file mode 100644
index 0000000..40d855f
--- /dev/null
+++ b/src/main/java/com/snp/batch/global/repository/screening/ShipRiskDetailHistoryRepository.java
@@ -0,0 +1,113 @@
+package com.snp.batch.global.repository.screening;
+
+import com.snp.batch.global.model.screening.ShipRiskDetailHistory;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ShipRiskDetailHistoryRepository extends JpaRepository {
+
+ @Query(nativeQuery = true, value = """
+ SELECT h.row_index, h.imo_no, h.last_mdfcn_dt, h.flctn_col_nm, h.bfr_val, h.aftr_val,
+ CASE h.flctn_col_nm
+ WHEN 'ais_notrcv_elps_days' THEN d.ais_notrcv_elps_days_desc
+ WHEN 'ais_lwrnk_days' THEN d.ais_lwrnk_days_desc
+ WHEN 'ais_up_imo_desc' THEN d.ais_up_imo_desc_val
+ WHEN 'othr_ship_nm_voy_yn' THEN d.othr_ship_nm_voy_yn_desc
+ WHEN 'mmsi_anom_message' THEN d.mmsi_anom_message_desc
+ WHEN 'recent_dark_actv' THEN d.recent_dark_actv_desc
+ WHEN 'port_prtcll' THEN d.port_prtcll_desc
+ WHEN 'port_risk' THEN d.port_risk_desc
+ WHEN 'sts_job' THEN d.sts_job_desc
+ WHEN 'drift_chg' THEN d.drift_chg_desc
+ WHEN 'risk_event' THEN d.risk_event_desc
+ WHEN 'ntnlty_chg' THEN d.ntnlty_chg_desc
+ WHEN 'ntnlty_prs_mou_perf' THEN d.ntnlty_prs_mou_perf_desc
+ WHEN 'ntnlty_tky_mou_perf' THEN d.ntnlty_tky_mou_perf_desc
+ WHEN 'ntnlty_uscg_mou_perf' THEN d.ntnlty_uscg_mou_perf_desc
+ WHEN 'uscg_excl_ship_cert' THEN d.uscg_excl_ship_cert_desc
+ WHEN 'psc_inspection_elps_hr' THEN d.psc_inspection_elps_hr_desc
+ WHEN 'psc_inspection' THEN d.psc_inspection_desc
+ WHEN 'psc_defect' THEN d.psc_defect_desc
+ WHEN 'psc_detained' THEN d.psc_detained_desc
+ WHEN 'now_smgrc_evdc' THEN d.now_smgrc_evdc_desc
+ WHEN 'docc_chg' THEN d.docc_chg_desc
+ WHEN 'now_clfic' THEN d.now_clfic_desc
+ WHEN 'clfic_status_chg' THEN d.clfic_status_chg_desc
+ WHEN 'pni_insrnc' THEN d.pni_insrnc_desc
+ WHEN 'ship_nm_chg' THEN d.ship_nm_chg_desc
+ WHEN 'gbo_chg' THEN d.gbo_chg_desc
+ WHEN 'vslage' THEN d.vslage_desc
+ WHEN 'ilgl_fshr_viol' THEN d.ilgl_fshr_viol_desc
+ WHEN 'draft_chg' THEN d.draft_chg_desc
+ WHEN 'recent_sanction_prtcll' THEN d.recent_sanction_prtcll_desc
+ WHEN 'sngl_ship_voy' THEN d.sngl_ship_voy_desc
+ WHEN 'fltsfty' THEN d.fltsfty_desc
+ WHEN 'flt_psc' THEN d.flt_psc_desc
+ WHEN 'spc_inspection_ovdue' THEN d.spc_inspection_ovdue_desc
+ WHEN 'ownr_unk' THEN d.ownr_unk_desc
+ WHEN 'rss_port_call' THEN d.rss_port_call_desc
+ WHEN 'rss_ownr_reg' THEN d.rss_ownr_reg_desc
+ WHEN 'rss_sts' THEN d.rss_sts_desc
+ END as narrative,
+ CASE h.flctn_col_nm
+ WHEN 'ais_notrcv_elps_days' THEN p.ais_notrcv_elps_days_desc
+ WHEN 'ais_lwrnk_days' THEN p.ais_lwrnk_days_desc
+ WHEN 'ais_up_imo_desc' THEN p.ais_up_imo_desc_val
+ WHEN 'othr_ship_nm_voy_yn' THEN p.othr_ship_nm_voy_yn_desc
+ WHEN 'mmsi_anom_message' THEN p.mmsi_anom_message_desc
+ WHEN 'recent_dark_actv' THEN p.recent_dark_actv_desc
+ WHEN 'port_prtcll' THEN p.port_prtcll_desc
+ WHEN 'port_risk' THEN p.port_risk_desc
+ WHEN 'sts_job' THEN p.sts_job_desc
+ WHEN 'drift_chg' THEN p.drift_chg_desc
+ WHEN 'risk_event' THEN p.risk_event_desc
+ WHEN 'ntnlty_chg' THEN p.ntnlty_chg_desc
+ WHEN 'ntnlty_prs_mou_perf' THEN p.ntnlty_prs_mou_perf_desc
+ WHEN 'ntnlty_tky_mou_perf' THEN p.ntnlty_tky_mou_perf_desc
+ WHEN 'ntnlty_uscg_mou_perf' THEN p.ntnlty_uscg_mou_perf_desc
+ WHEN 'uscg_excl_ship_cert' THEN p.uscg_excl_ship_cert_desc
+ WHEN 'psc_inspection_elps_hr' THEN p.psc_inspection_elps_hr_desc
+ WHEN 'psc_inspection' THEN p.psc_inspection_desc
+ WHEN 'psc_defect' THEN p.psc_defect_desc
+ WHEN 'psc_detained' THEN p.psc_detained_desc
+ WHEN 'now_smgrc_evdc' THEN p.now_smgrc_evdc_desc
+ WHEN 'docc_chg' THEN p.docc_chg_desc
+ WHEN 'now_clfic' THEN p.now_clfic_desc
+ WHEN 'clfic_status_chg' THEN p.clfic_status_chg_desc
+ WHEN 'pni_insrnc' THEN p.pni_insrnc_desc
+ WHEN 'ship_nm_chg' THEN p.ship_nm_chg_desc
+ WHEN 'gbo_chg' THEN p.gbo_chg_desc
+ WHEN 'vslage' THEN p.vslage_desc
+ WHEN 'ilgl_fshr_viol' THEN p.ilgl_fshr_viol_desc
+ WHEN 'draft_chg' THEN p.draft_chg_desc
+ WHEN 'recent_sanction_prtcll' THEN p.recent_sanction_prtcll_desc
+ WHEN 'sngl_ship_voy' THEN p.sngl_ship_voy_desc
+ WHEN 'fltsfty' THEN p.fltsfty_desc
+ WHEN 'flt_psc' THEN p.flt_psc_desc
+ WHEN 'spc_inspection_ovdue' THEN p.spc_inspection_ovdue_desc
+ WHEN 'ownr_unk' THEN p.ownr_unk_desc
+ WHEN 'rss_port_call' THEN p.rss_port_call_desc
+ WHEN 'rss_ownr_reg' THEN p.rss_ownr_reg_desc
+ WHEN 'rss_sts' THEN p.rss_sts_desc
+ END as prev_narrative
+ FROM std_snp_svc.tb_ship_risk_detail_info_hstry h
+ LEFT JOIN std_snp_svc.tb_ship_risk_detail_hstry d
+ ON h.imo_no = d.imo_no AND h.last_mdfcn_dt = d.last_mdfcn_dt
+ LEFT JOIN LATERAL (
+ SELECT *
+ FROM std_snp_svc.tb_ship_risk_detail_hstry prev
+ WHERE prev.imo_no = h.imo_no
+ AND prev.last_mdfcn_dt < h.last_mdfcn_dt
+ ORDER BY prev.last_mdfcn_dt DESC
+ LIMIT 1
+ ) p ON true
+ WHERE h.imo_no = :imoNo
+ ORDER BY h.last_mdfcn_dt DESC
+ """)
+ List findRiskHistoryWithNarrative(@Param("imoNo") String imoNo);
+}
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/config/FlagCodeImportJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/common/config/FlagCodeImportJobConfig.java
similarity index 89%
rename from src/main/java/com/snp/batch/jobs/common/batch/config/FlagCodeImportJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/common/config/FlagCodeImportJobConfig.java
index f30fcc9..87faea3 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/config/FlagCodeImportJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/config/FlagCodeImportJobConfig.java
@@ -1,13 +1,13 @@
-package com.snp.batch.jobs.common.batch.config;
+package com.snp.batch.jobs.batch.common.config;
import com.snp.batch.common.batch.config.BaseJobConfig;
-import com.snp.batch.jobs.common.batch.dto.FlagCodeDto;
-import com.snp.batch.jobs.common.batch.entity.FlagCodeEntity;
-import com.snp.batch.jobs.common.batch.processor.FlagCodeDataProcessor;
-import com.snp.batch.jobs.common.batch.reader.FlagCodeDataReader;
-import com.snp.batch.jobs.common.batch.repository.FlagCodeRepository;
-import com.snp.batch.jobs.common.batch.writer.FlagCodeDataWriter;
-import com.snp.batch.jobs.facility.batch.reader.PortDataReader;
+import com.snp.batch.jobs.batch.common.dto.FlagCodeDto;
+import com.snp.batch.jobs.batch.common.entity.FlagCodeEntity;
+import com.snp.batch.jobs.batch.common.processor.FlagCodeDataProcessor;
+import com.snp.batch.jobs.batch.common.reader.FlagCodeDataReader;
+import com.snp.batch.jobs.batch.common.repository.FlagCodeRepository;
+import com.snp.batch.jobs.batch.common.writer.FlagCodeDataWriter;
+import com.snp.batch.jobs.batch.facility.reader.PortDataReader;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/config/Stat5CodeImportJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/common/config/Stat5CodeImportJobConfig.java
similarity index 89%
rename from src/main/java/com/snp/batch/jobs/common/batch/config/Stat5CodeImportJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/common/config/Stat5CodeImportJobConfig.java
index b27b652..24daba1 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/config/Stat5CodeImportJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/config/Stat5CodeImportJobConfig.java
@@ -1,12 +1,12 @@
-package com.snp.batch.jobs.common.batch.config;
+package com.snp.batch.jobs.batch.common.config;
import com.snp.batch.common.batch.config.BaseJobConfig;
-import com.snp.batch.jobs.common.batch.dto.Stat5CodeDto;
-import com.snp.batch.jobs.common.batch.entity.Stat5CodeEntity;
-import com.snp.batch.jobs.common.batch.processor.Stat5CodeDataProcessor;
-import com.snp.batch.jobs.common.batch.reader.Stat5CodeDataReader;
-import com.snp.batch.jobs.common.batch.repository.Stat5CodeRepository;
-import com.snp.batch.jobs.common.batch.writer.Stat5CodeDataWriter;
+import com.snp.batch.jobs.batch.common.dto.Stat5CodeDto;
+import com.snp.batch.jobs.batch.common.entity.Stat5CodeEntity;
+import com.snp.batch.jobs.batch.common.processor.Stat5CodeDataProcessor;
+import com.snp.batch.jobs.batch.common.reader.Stat5CodeDataReader;
+import com.snp.batch.jobs.batch.common.repository.Stat5CodeRepository;
+import com.snp.batch.jobs.batch.common.writer.Stat5CodeDataWriter;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/dto/FlagCodeApiResponse.java b/src/main/java/com/snp/batch/jobs/batch/common/dto/FlagCodeApiResponse.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/common/batch/dto/FlagCodeApiResponse.java
rename to src/main/java/com/snp/batch/jobs/batch/common/dto/FlagCodeApiResponse.java
index 3e3a51f..11ecc8f 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/dto/FlagCodeApiResponse.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/dto/FlagCodeApiResponse.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.common.batch.dto;
+package com.snp.batch.jobs.batch.common.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/dto/FlagCodeDto.java b/src/main/java/com/snp/batch/jobs/batch/common/dto/FlagCodeDto.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/common/batch/dto/FlagCodeDto.java
rename to src/main/java/com/snp/batch/jobs/batch/common/dto/FlagCodeDto.java
index c763da7..f8469bb 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/dto/FlagCodeDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/dto/FlagCodeDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.common.batch.dto;
+package com.snp.batch.jobs.batch.common.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/dto/Stat5CodeApiResponse.java b/src/main/java/com/snp/batch/jobs/batch/common/dto/Stat5CodeApiResponse.java
similarity index 90%
rename from src/main/java/com/snp/batch/jobs/common/batch/dto/Stat5CodeApiResponse.java
rename to src/main/java/com/snp/batch/jobs/batch/common/dto/Stat5CodeApiResponse.java
index f8f60e1..9cb25d2 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/dto/Stat5CodeApiResponse.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/dto/Stat5CodeApiResponse.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.common.batch.dto;
+package com.snp.batch.jobs.batch.common.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/dto/Stat5CodeDto.java b/src/main/java/com/snp/batch/jobs/batch/common/dto/Stat5CodeDto.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/common/batch/dto/Stat5CodeDto.java
rename to src/main/java/com/snp/batch/jobs/batch/common/dto/Stat5CodeDto.java
index c50fc10..e851e4b 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/dto/Stat5CodeDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/dto/Stat5CodeDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.common.batch.dto;
+package com.snp.batch.jobs.batch.common.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/entity/FlagCodeEntity.java b/src/main/java/com/snp/batch/jobs/batch/common/entity/FlagCodeEntity.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/common/batch/entity/FlagCodeEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/common/entity/FlagCodeEntity.java
index 995d108..e08384e 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/entity/FlagCodeEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/entity/FlagCodeEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.common.batch.entity;
+package com.snp.batch.jobs.batch.common.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/entity/Stat5CodeEntity.java b/src/main/java/com/snp/batch/jobs/batch/common/entity/Stat5CodeEntity.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/common/batch/entity/Stat5CodeEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/common/entity/Stat5CodeEntity.java
index b5e2d76..e527b4d 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/entity/Stat5CodeEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/entity/Stat5CodeEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.common.batch.entity;
+package com.snp.batch.jobs.batch.common.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/processor/FlagCodeDataProcessor.java b/src/main/java/com/snp/batch/jobs/batch/common/processor/FlagCodeDataProcessor.java
similarity index 86%
rename from src/main/java/com/snp/batch/jobs/common/batch/processor/FlagCodeDataProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/common/processor/FlagCodeDataProcessor.java
index a5f95b1..1d3d21e 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/processor/FlagCodeDataProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/processor/FlagCodeDataProcessor.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.common.batch.processor;
+package com.snp.batch.jobs.batch.common.processor;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.common.batch.dto.FlagCodeDto;
-import com.snp.batch.jobs.common.batch.entity.FlagCodeEntity;
+import com.snp.batch.jobs.batch.common.dto.FlagCodeDto;
+import com.snp.batch.jobs.batch.common.entity.FlagCodeEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/processor/Stat5CodeDataProcessor.java b/src/main/java/com/snp/batch/jobs/batch/common/processor/Stat5CodeDataProcessor.java
similarity index 89%
rename from src/main/java/com/snp/batch/jobs/common/batch/processor/Stat5CodeDataProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/common/processor/Stat5CodeDataProcessor.java
index 27fa993..4f58b96 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/processor/Stat5CodeDataProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/processor/Stat5CodeDataProcessor.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.common.batch.processor;
+package com.snp.batch.jobs.batch.common.processor;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.common.batch.dto.Stat5CodeDto;
-import com.snp.batch.jobs.common.batch.entity.Stat5CodeEntity;
+import com.snp.batch.jobs.batch.common.dto.Stat5CodeDto;
+import com.snp.batch.jobs.batch.common.entity.Stat5CodeEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/reader/FlagCodeDataReader.java b/src/main/java/com/snp/batch/jobs/batch/common/reader/FlagCodeDataReader.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/common/batch/reader/FlagCodeDataReader.java
rename to src/main/java/com/snp/batch/jobs/batch/common/reader/FlagCodeDataReader.java
index 544851e..087f08a 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/reader/FlagCodeDataReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/reader/FlagCodeDataReader.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.common.batch.reader;
+package com.snp.batch.jobs.batch.common.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.common.batch.dto.FlagCodeApiResponse;
-import com.snp.batch.jobs.common.batch.dto.FlagCodeDto;
+import com.snp.batch.jobs.batch.common.dto.FlagCodeApiResponse;
+import com.snp.batch.jobs.batch.common.dto.FlagCodeDto;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.reactive.function.client.WebClient;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/reader/Stat5CodeDataReader.java b/src/main/java/com/snp/batch/jobs/batch/common/reader/Stat5CodeDataReader.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/common/batch/reader/Stat5CodeDataReader.java
rename to src/main/java/com/snp/batch/jobs/batch/common/reader/Stat5CodeDataReader.java
index e887aa0..06cd146 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/reader/Stat5CodeDataReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/reader/Stat5CodeDataReader.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.common.batch.reader;
+package com.snp.batch.jobs.batch.common.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.common.batch.dto.Stat5CodeApiResponse;
-import com.snp.batch.jobs.common.batch.dto.Stat5CodeDto;
+import com.snp.batch.jobs.batch.common.dto.Stat5CodeApiResponse;
+import com.snp.batch.jobs.batch.common.dto.Stat5CodeDto;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.reactive.function.client.WebClient;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/repository/FlagCodeRepository.java b/src/main/java/com/snp/batch/jobs/batch/common/repository/FlagCodeRepository.java
similarity index 51%
rename from src/main/java/com/snp/batch/jobs/common/batch/repository/FlagCodeRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/common/repository/FlagCodeRepository.java
index 304bb8b..46ced31 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/repository/FlagCodeRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/repository/FlagCodeRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.common.batch.repository;
+package com.snp.batch.jobs.batch.common.repository;
-import com.snp.batch.jobs.common.batch.entity.FlagCodeEntity;
+import com.snp.batch.jobs.batch.common.entity.FlagCodeEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/repository/FlagCodeRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/common/repository/FlagCodeRepositoryImpl.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/common/batch/repository/FlagCodeRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/common/repository/FlagCodeRepositoryImpl.java
index 3a78ad8..82d3081 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/repository/FlagCodeRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/repository/FlagCodeRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.common.batch.repository;
+package com.snp.batch.jobs.batch.common.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.common.batch.entity.FlagCodeEntity;
+import com.snp.batch.jobs.batch.common.entity.FlagCodeEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/repository/Stat5CodeRepository.java b/src/main/java/com/snp/batch/jobs/batch/common/repository/Stat5CodeRepository.java
similarity index 51%
rename from src/main/java/com/snp/batch/jobs/common/batch/repository/Stat5CodeRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/common/repository/Stat5CodeRepository.java
index 10edd49..ccfb173 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/repository/Stat5CodeRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/repository/Stat5CodeRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.common.batch.repository;
+package com.snp.batch.jobs.batch.common.repository;
-import com.snp.batch.jobs.common.batch.entity.Stat5CodeEntity;
+import com.snp.batch.jobs.batch.common.entity.Stat5CodeEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/repository/Stat5CodeRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/common/repository/Stat5CodeRepositoryImpl.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/common/batch/repository/Stat5CodeRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/common/repository/Stat5CodeRepositoryImpl.java
index bd52cd5..06b1bbe 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/repository/Stat5CodeRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/repository/Stat5CodeRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.common.batch.repository;
+package com.snp.batch.jobs.batch.common.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.common.batch.entity.Stat5CodeEntity;
+import com.snp.batch.jobs.batch.common.entity.Stat5CodeEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/writer/FlagCodeDataWriter.java b/src/main/java/com/snp/batch/jobs/batch/common/writer/FlagCodeDataWriter.java
similarity index 78%
rename from src/main/java/com/snp/batch/jobs/common/batch/writer/FlagCodeDataWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/common/writer/FlagCodeDataWriter.java
index 5c5b82e..6cd64a0 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/writer/FlagCodeDataWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/writer/FlagCodeDataWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.common.batch.writer;
+package com.snp.batch.jobs.batch.common.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.common.batch.entity.FlagCodeEntity;
-import com.snp.batch.jobs.common.batch.repository.FlagCodeRepository;
+import com.snp.batch.jobs.batch.common.entity.FlagCodeEntity;
+import com.snp.batch.jobs.batch.common.repository.FlagCodeRepository;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/common/batch/writer/Stat5CodeDataWriter.java b/src/main/java/com/snp/batch/jobs/batch/common/writer/Stat5CodeDataWriter.java
similarity index 78%
rename from src/main/java/com/snp/batch/jobs/common/batch/writer/Stat5CodeDataWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/common/writer/Stat5CodeDataWriter.java
index 9f8267e..c78bc95 100644
--- a/src/main/java/com/snp/batch/jobs/common/batch/writer/Stat5CodeDataWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/common/writer/Stat5CodeDataWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.common.batch.writer;
+package com.snp.batch.jobs.batch.common.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.common.batch.entity.Stat5CodeEntity;
-import com.snp.batch.jobs.common.batch.repository.Stat5CodeRepository;
+import com.snp.batch.jobs.batch.common.entity.Stat5CodeEntity;
+import com.snp.batch.jobs.batch.common.repository.Stat5CodeRepository;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/config/CompanyComplianceImportRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/compliance/config/CompanyComplianceImportRangeJobConfig.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/config/CompanyComplianceImportRangeJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/config/CompanyComplianceImportRangeJobConfig.java
index a4ce742..74e45e1 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/config/CompanyComplianceImportRangeJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/config/CompanyComplianceImportRangeJobConfig.java
@@ -1,12 +1,12 @@
-package com.snp.batch.jobs.compliance.batch.config;
+package com.snp.batch.jobs.batch.compliance.config;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.compliance.batch.dto.CompanyComplianceDto;
-import com.snp.batch.jobs.compliance.batch.entity.CompanyComplianceEntity;
-import com.snp.batch.jobs.compliance.batch.processor.CompanyComplianceDataProcessor;
-import com.snp.batch.jobs.compliance.batch.reader.CompanyComplianceDataRangeReader;
-import com.snp.batch.jobs.compliance.batch.writer.CompanyComplianceDataWriter;
+import com.snp.batch.jobs.batch.compliance.dto.CompanyComplianceDto;
+import com.snp.batch.jobs.batch.compliance.entity.CompanyComplianceEntity;
+import com.snp.batch.jobs.batch.compliance.processor.CompanyComplianceDataProcessor;
+import com.snp.batch.jobs.batch.compliance.reader.CompanyComplianceDataRangeReader;
+import com.snp.batch.jobs.batch.compliance.writer.CompanyComplianceDataWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/config/ComplianceImportRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/compliance/config/ComplianceImportRangeJobConfig.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/config/ComplianceImportRangeJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/config/ComplianceImportRangeJobConfig.java
index fa496d2..463c767 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/config/ComplianceImportRangeJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/config/ComplianceImportRangeJobConfig.java
@@ -1,12 +1,12 @@
-package com.snp.batch.jobs.compliance.batch.config;
+package com.snp.batch.jobs.batch.compliance.config;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.compliance.batch.dto.ComplianceDto;
-import com.snp.batch.jobs.compliance.batch.entity.ComplianceEntity;
-import com.snp.batch.jobs.compliance.batch.processor.ComplianceDataProcessor;
-import com.snp.batch.jobs.compliance.batch.reader.ComplianceDataRangeReader;
-import com.snp.batch.jobs.compliance.batch.writer.ComplianceDataWriter;
+import com.snp.batch.jobs.batch.compliance.dto.ComplianceDto;
+import com.snp.batch.jobs.batch.compliance.entity.ComplianceEntity;
+import com.snp.batch.jobs.batch.compliance.processor.ComplianceDataProcessor;
+import com.snp.batch.jobs.batch.compliance.reader.ComplianceDataRangeReader;
+import com.snp.batch.jobs.batch.compliance.writer.ComplianceDataWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/dto/CompanyComplianceDto.java b/src/main/java/com/snp/batch/jobs/batch/compliance/dto/CompanyComplianceDto.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/dto/CompanyComplianceDto.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/dto/CompanyComplianceDto.java
index ecbc837..1d47c00 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/dto/CompanyComplianceDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/dto/CompanyComplianceDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.compliance.batch.dto;
+package com.snp.batch.jobs.batch.compliance.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/dto/ComplianceDto.java b/src/main/java/com/snp/batch/jobs/batch/compliance/dto/ComplianceDto.java
similarity index 98%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/dto/ComplianceDto.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/dto/ComplianceDto.java
index 4b7d032..683145b 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/dto/ComplianceDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/dto/ComplianceDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.compliance.batch.dto;
+package com.snp.batch.jobs.batch.compliance.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/entity/CompanyComplianceEntity.java b/src/main/java/com/snp/batch/jobs/batch/compliance/entity/CompanyComplianceEntity.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/entity/CompanyComplianceEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/entity/CompanyComplianceEntity.java
index 1ea272c..6515242 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/entity/CompanyComplianceEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/entity/CompanyComplianceEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.compliance.batch.entity;
+package com.snp.batch.jobs.batch.compliance.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/entity/ComplianceEntity.java b/src/main/java/com/snp/batch/jobs/batch/compliance/entity/ComplianceEntity.java
similarity index 98%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/entity/ComplianceEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/entity/ComplianceEntity.java
index e363042..c49ac02 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/entity/ComplianceEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/entity/ComplianceEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.compliance.batch.entity;
+package com.snp.batch.jobs.batch.compliance.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/processor/CompanyComplianceDataProcessor.java b/src/main/java/com/snp/batch/jobs/batch/compliance/processor/CompanyComplianceDataProcessor.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/processor/CompanyComplianceDataProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/processor/CompanyComplianceDataProcessor.java
index 211ba1c..7ce2d3b 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/processor/CompanyComplianceDataProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/processor/CompanyComplianceDataProcessor.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.compliance.batch.processor;
+package com.snp.batch.jobs.batch.compliance.processor;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.compliance.batch.dto.CompanyComplianceDto;
-import com.snp.batch.jobs.compliance.batch.entity.CompanyComplianceEntity;
+import com.snp.batch.jobs.batch.compliance.dto.CompanyComplianceDto;
+import com.snp.batch.jobs.batch.compliance.entity.CompanyComplianceEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/processor/ComplianceDataProcessor.java b/src/main/java/com/snp/batch/jobs/batch/compliance/processor/ComplianceDataProcessor.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/processor/ComplianceDataProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/processor/ComplianceDataProcessor.java
index 7145776..a33c7f3 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/processor/ComplianceDataProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/processor/ComplianceDataProcessor.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.compliance.batch.processor;
+package com.snp.batch.jobs.batch.compliance.processor;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.compliance.batch.dto.ComplianceDto;
-import com.snp.batch.jobs.compliance.batch.entity.ComplianceEntity;
+import com.snp.batch.jobs.batch.compliance.dto.ComplianceDto;
+import com.snp.batch.jobs.batch.compliance.entity.ComplianceEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/reader/CompanyComplianceDataRangeReader.java b/src/main/java/com/snp/batch/jobs/batch/compliance/reader/CompanyComplianceDataRangeReader.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/reader/CompanyComplianceDataRangeReader.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/reader/CompanyComplianceDataRangeReader.java
index 6170041..5e76273 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/reader/CompanyComplianceDataRangeReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/reader/CompanyComplianceDataRangeReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.compliance.batch.reader;
+package com.snp.batch.jobs.batch.compliance.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.compliance.batch.dto.CompanyComplianceDto;
+import com.snp.batch.jobs.batch.compliance.dto.CompanyComplianceDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/reader/ComplianceDataRangeReader.java b/src/main/java/com/snp/batch/jobs/batch/compliance/reader/ComplianceDataRangeReader.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/reader/ComplianceDataRangeReader.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/reader/ComplianceDataRangeReader.java
index 6c5c185..ee41d5a 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/reader/ComplianceDataRangeReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/reader/ComplianceDataRangeReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.compliance.batch.reader;
+package com.snp.batch.jobs.batch.compliance.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.compliance.batch.dto.ComplianceDto;
+import com.snp.batch.jobs.batch.compliance.dto.ComplianceDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/repository/CompanyComplianceRepository.java b/src/main/java/com/snp/batch/jobs/batch/compliance/repository/CompanyComplianceRepository.java
similarity index 66%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/repository/CompanyComplianceRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/repository/CompanyComplianceRepository.java
index 6277eec..073ccb9 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/repository/CompanyComplianceRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/repository/CompanyComplianceRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.compliance.batch.repository;
+package com.snp.batch.jobs.batch.compliance.repository;
-import com.snp.batch.jobs.compliance.batch.entity.CompanyComplianceEntity;
+import com.snp.batch.jobs.batch.compliance.entity.CompanyComplianceEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/repository/CompanyComplianceRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/compliance/repository/CompanyComplianceRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/repository/CompanyComplianceRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/repository/CompanyComplianceRepositoryImpl.java
index 08ded44..05dddb8 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/repository/CompanyComplianceRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/repository/CompanyComplianceRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.compliance.batch.repository;
+package com.snp.batch.jobs.batch.compliance.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.compliance.batch.entity.CompanyComplianceEntity;
+import com.snp.batch.jobs.batch.compliance.entity.CompanyComplianceEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/repository/ComplianceRepository.java b/src/main/java/com/snp/batch/jobs/batch/compliance/repository/ComplianceRepository.java
similarity index 62%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/repository/ComplianceRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/repository/ComplianceRepository.java
index b34e42c..94e193d 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/repository/ComplianceRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/repository/ComplianceRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.compliance.batch.repository;
+package com.snp.batch.jobs.batch.compliance.repository;
-import com.snp.batch.jobs.compliance.batch.entity.ComplianceEntity;
+import com.snp.batch.jobs.batch.compliance.entity.ComplianceEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/repository/ComplianceRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/compliance/repository/ComplianceRepositoryImpl.java
similarity index 98%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/repository/ComplianceRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/repository/ComplianceRepositoryImpl.java
index 3a4b365..346ff68 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/repository/ComplianceRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/repository/ComplianceRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.compliance.batch.repository;
+package com.snp.batch.jobs.batch.compliance.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.compliance.batch.entity.ComplianceEntity;
+import com.snp.batch.jobs.batch.compliance.entity.ComplianceEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/writer/CompanyComplianceDataWriter.java b/src/main/java/com/snp/batch/jobs/batch/compliance/writer/CompanyComplianceDataWriter.java
similarity index 81%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/writer/CompanyComplianceDataWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/writer/CompanyComplianceDataWriter.java
index 1f75813..0048638 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/writer/CompanyComplianceDataWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/writer/CompanyComplianceDataWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.compliance.batch.writer;
+package com.snp.batch.jobs.batch.compliance.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.compliance.batch.entity.CompanyComplianceEntity;
-import com.snp.batch.jobs.compliance.batch.repository.CompanyComplianceRepository;
+import com.snp.batch.jobs.batch.compliance.entity.CompanyComplianceEntity;
+import com.snp.batch.jobs.batch.compliance.repository.CompanyComplianceRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/writer/ComplianceDataWriter.java b/src/main/java/com/snp/batch/jobs/batch/compliance/writer/ComplianceDataWriter.java
similarity index 80%
rename from src/main/java/com/snp/batch/jobs/compliance/batch/writer/ComplianceDataWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/compliance/writer/ComplianceDataWriter.java
index e102db3..ef842e3 100644
--- a/src/main/java/com/snp/batch/jobs/compliance/batch/writer/ComplianceDataWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/compliance/writer/ComplianceDataWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.compliance.batch.writer;
+package com.snp.batch.jobs.batch.compliance.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.compliance.batch.entity.ComplianceEntity;
-import com.snp.batch.jobs.compliance.batch.repository.ComplianceRepository;
+import com.snp.batch.jobs.batch.compliance.entity.ComplianceEntity;
+import com.snp.batch.jobs.batch.compliance.repository.ComplianceRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/config/EventImportJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/event/config/EventImportJobConfig.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/event/batch/config/EventImportJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/event/config/EventImportJobConfig.java
index d7dd1c8..9f93445 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/config/EventImportJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/config/EventImportJobConfig.java
@@ -1,12 +1,12 @@
-package com.snp.batch.jobs.event.batch.config;
+package com.snp.batch.jobs.batch.event.config;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.event.batch.dto.EventDetailDto;
-import com.snp.batch.jobs.event.batch.entity.EventDetailEntity;
-import com.snp.batch.jobs.event.batch.processor.EventDataProcessor;
-import com.snp.batch.jobs.event.batch.reader.EventDataReader;
-import com.snp.batch.jobs.event.batch.writer.EventDataWriter;
+import com.snp.batch.jobs.batch.event.dto.EventDetailDto;
+import com.snp.batch.jobs.batch.event.entity.EventDetailEntity;
+import com.snp.batch.jobs.batch.event.processor.EventDataProcessor;
+import com.snp.batch.jobs.batch.event.reader.EventDataReader;
+import com.snp.batch.jobs.batch.event.writer.EventDataWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/dto/CargoDto.java b/src/main/java/com/snp/batch/jobs/batch/event/dto/CargoDto.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/event/batch/dto/CargoDto.java
rename to src/main/java/com/snp/batch/jobs/batch/event/dto/CargoDto.java
index 8a91382..0d57792 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/dto/CargoDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/dto/CargoDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.event.batch.dto;
+package com.snp.batch.jobs.batch.event.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.event.batch.entity.CargoEntity;
+import com.snp.batch.jobs.batch.event.entity.CargoEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/dto/EventDetailDto.java b/src/main/java/com/snp/batch/jobs/batch/event/dto/EventDetailDto.java
similarity index 98%
rename from src/main/java/com/snp/batch/jobs/event/batch/dto/EventDetailDto.java
rename to src/main/java/com/snp/batch/jobs/batch/event/dto/EventDetailDto.java
index 38a2fd6..93b90df 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/dto/EventDetailDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/dto/EventDetailDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.event.batch.dto;
+package com.snp.batch.jobs.batch.event.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/dto/EventDetailResponse.java b/src/main/java/com/snp/batch/jobs/batch/event/dto/EventDetailResponse.java
similarity index 89%
rename from src/main/java/com/snp/batch/jobs/event/batch/dto/EventDetailResponse.java
rename to src/main/java/com/snp/batch/jobs/batch/event/dto/EventDetailResponse.java
index fe67261..36fbd8a 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/dto/EventDetailResponse.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/dto/EventDetailResponse.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.event.batch.dto;
+package com.snp.batch.jobs.batch.event.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/dto/EventDto.java b/src/main/java/com/snp/batch/jobs/batch/event/dto/EventDto.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/event/batch/dto/EventDto.java
rename to src/main/java/com/snp/batch/jobs/batch/event/dto/EventDto.java
index 00d2e07..06a46ac 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/dto/EventDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/dto/EventDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.event.batch.dto;
+package com.snp.batch.jobs.batch.event.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/dto/EventPeriod.java b/src/main/java/com/snp/batch/jobs/batch/event/dto/EventPeriod.java
similarity index 82%
rename from src/main/java/com/snp/batch/jobs/event/batch/dto/EventPeriod.java
rename to src/main/java/com/snp/batch/jobs/batch/event/dto/EventPeriod.java
index 05e4703..79e6b75 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/dto/EventPeriod.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/dto/EventPeriod.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.event.batch.dto;
+package com.snp.batch.jobs.batch.event.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/dto/EventResponse.java b/src/main/java/com/snp/batch/jobs/batch/event/dto/EventResponse.java
similarity index 90%
rename from src/main/java/com/snp/batch/jobs/event/batch/dto/EventResponse.java
rename to src/main/java/com/snp/batch/jobs/batch/event/dto/EventResponse.java
index 7c9118c..d701253 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/dto/EventResponse.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/dto/EventResponse.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.event.batch.dto;
+package com.snp.batch.jobs.batch.event.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/dto/HumanCasualtyDto.java b/src/main/java/com/snp/batch/jobs/batch/event/dto/HumanCasualtyDto.java
similarity index 88%
rename from src/main/java/com/snp/batch/jobs/event/batch/dto/HumanCasualtyDto.java
rename to src/main/java/com/snp/batch/jobs/batch/event/dto/HumanCasualtyDto.java
index 09ed21c..543db48 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/dto/HumanCasualtyDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/dto/HumanCasualtyDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.event.batch.dto;
+package com.snp.batch.jobs.batch.event.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.event.batch.entity.HumanCasualtyEntity;
+import com.snp.batch.jobs.batch.event.entity.HumanCasualtyEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/dto/RelationshipDto.java b/src/main/java/com/snp/batch/jobs/batch/event/dto/RelationshipDto.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/event/batch/dto/RelationshipDto.java
rename to src/main/java/com/snp/batch/jobs/batch/event/dto/RelationshipDto.java
index 1d1beae..45b57fa 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/dto/RelationshipDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/dto/RelationshipDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.event.batch.dto;
+package com.snp.batch.jobs.batch.event.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.event.batch.entity.RelationshipEntity;
+import com.snp.batch.jobs.batch.event.entity.RelationshipEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/entity/CargoEntity.java b/src/main/java/com/snp/batch/jobs/batch/event/entity/CargoEntity.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/event/batch/entity/CargoEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/event/entity/CargoEntity.java
index 8e2e95d..ad3799e 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/entity/CargoEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/entity/CargoEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.event.batch.entity;
+package com.snp.batch.jobs.batch.event.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/entity/EventDetailEntity.java b/src/main/java/com/snp/batch/jobs/batch/event/entity/EventDetailEntity.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/event/batch/entity/EventDetailEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/event/entity/EventDetailEntity.java
index 58b4bda..f159f9c 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/entity/EventDetailEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/entity/EventDetailEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.event.batch.entity;
+package com.snp.batch.jobs.batch.event.entity;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.snp.batch.common.batch.entity.BaseEntity;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/entity/EventEntity.java b/src/main/java/com/snp/batch/jobs/batch/event/entity/EventEntity.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/event/batch/entity/EventEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/event/entity/EventEntity.java
index 6a55161..813ae9d 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/entity/EventEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/entity/EventEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.event.batch.entity;
+package com.snp.batch.jobs.batch.event.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/entity/HumanCasualtyEntity.java b/src/main/java/com/snp/batch/jobs/batch/event/entity/HumanCasualtyEntity.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/event/batch/entity/HumanCasualtyEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/event/entity/HumanCasualtyEntity.java
index d52bd9e..c511a08 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/entity/HumanCasualtyEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/entity/HumanCasualtyEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.event.batch.entity;
+package com.snp.batch.jobs.batch.event.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/entity/RelationshipEntity.java b/src/main/java/com/snp/batch/jobs/batch/event/entity/RelationshipEntity.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/event/batch/entity/RelationshipEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/event/entity/RelationshipEntity.java
index e3c5ea7..014fa26 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/entity/RelationshipEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/entity/RelationshipEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.event.batch.entity;
+package com.snp.batch.jobs.batch.event.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/processor/EventDataProcessor.java b/src/main/java/com/snp/batch/jobs/batch/event/processor/EventDataProcessor.java
similarity index 89%
rename from src/main/java/com/snp/batch/jobs/event/batch/processor/EventDataProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/event/processor/EventDataProcessor.java
index 899a04b..f8876c5 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/processor/EventDataProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/processor/EventDataProcessor.java
@@ -1,15 +1,15 @@
-package com.snp.batch.jobs.event.batch.processor;
+package com.snp.batch.jobs.batch.event.processor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.event.batch.dto.CargoDto;
-import com.snp.batch.jobs.event.batch.dto.EventDetailDto;
-import com.snp.batch.jobs.event.batch.dto.HumanCasualtyDto;
-import com.snp.batch.jobs.event.batch.dto.RelationshipDto;
-import com.snp.batch.jobs.event.batch.entity.CargoEntity;
-import com.snp.batch.jobs.event.batch.entity.EventDetailEntity;
-import com.snp.batch.jobs.event.batch.entity.HumanCasualtyEntity;
-import com.snp.batch.jobs.event.batch.entity.RelationshipEntity;
+import com.snp.batch.jobs.batch.event.dto.CargoDto;
+import com.snp.batch.jobs.batch.event.dto.EventDetailDto;
+import com.snp.batch.jobs.batch.event.dto.HumanCasualtyDto;
+import com.snp.batch.jobs.batch.event.dto.RelationshipDto;
+import com.snp.batch.jobs.batch.event.entity.CargoEntity;
+import com.snp.batch.jobs.batch.event.entity.EventDetailEntity;
+import com.snp.batch.jobs.batch.event.entity.HumanCasualtyEntity;
+import com.snp.batch.jobs.batch.event.entity.RelationshipEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/reader/EventDataReader.java b/src/main/java/com/snp/batch/jobs/batch/event/reader/EventDataReader.java
similarity index 99%
rename from src/main/java/com/snp/batch/jobs/event/batch/reader/EventDataReader.java
rename to src/main/java/com/snp/batch/jobs/batch/event/reader/EventDataReader.java
index 602c2b5..ca96c57 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/reader/EventDataReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/reader/EventDataReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.event.batch.reader;
+package com.snp.batch.jobs.batch.event.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.event.batch.dto.*;
+import com.snp.batch.jobs.batch.event.dto.*;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/batch/event/repository/EventRepository.java b/src/main/java/com/snp/batch/jobs/batch/event/repository/EventRepository.java
new file mode 100644
index 0000000..7cf97e0
--- /dev/null
+++ b/src/main/java/com/snp/batch/jobs/batch/event/repository/EventRepository.java
@@ -0,0 +1,15 @@
+package com.snp.batch.jobs.batch.event.repository;
+
+import com.snp.batch.jobs.batch.event.entity.CargoEntity;
+import com.snp.batch.jobs.batch.event.entity.EventDetailEntity;
+import com.snp.batch.jobs.batch.event.entity.HumanCasualtyEntity;
+import com.snp.batch.jobs.batch.event.entity.RelationshipEntity;
+
+import java.util.List;
+
+public interface EventRepository {
+ void saveEventAll(List items);
+ void saveCargoAll(List items);
+ void saveHumanCasualtyAll(List items);
+ void saveRelationshipAll(List items);
+}
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/repository/EventRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/event/repository/EventRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/event/batch/repository/EventRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/event/repository/EventRepositoryImpl.java
index abee759..e595e48 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/repository/EventRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/repository/EventRepositoryImpl.java
@@ -1,10 +1,10 @@
-package com.snp.batch.jobs.event.batch.repository;
+package com.snp.batch.jobs.batch.event.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.event.batch.entity.CargoEntity;
-import com.snp.batch.jobs.event.batch.entity.EventDetailEntity;
-import com.snp.batch.jobs.event.batch.entity.HumanCasualtyEntity;
-import com.snp.batch.jobs.event.batch.entity.RelationshipEntity;
+import com.snp.batch.jobs.batch.event.entity.CargoEntity;
+import com.snp.batch.jobs.batch.event.entity.EventDetailEntity;
+import com.snp.batch.jobs.batch.event.entity.HumanCasualtyEntity;
+import com.snp.batch.jobs.batch.event.entity.RelationshipEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/repository/EventSql.java b/src/main/java/com/snp/batch/jobs/batch/event/repository/EventSql.java
similarity index 98%
rename from src/main/java/com/snp/batch/jobs/event/batch/repository/EventSql.java
rename to src/main/java/com/snp/batch/jobs/batch/event/repository/EventSql.java
index 8e25561..b7bcec4 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/repository/EventSql.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/repository/EventSql.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.event.batch.repository;
+package com.snp.batch.jobs.batch.event.repository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/writer/EventDataWriter.java b/src/main/java/com/snp/batch/jobs/batch/event/writer/EventDataWriter.java
similarity index 89%
rename from src/main/java/com/snp/batch/jobs/event/batch/writer/EventDataWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/event/writer/EventDataWriter.java
index 7185f9c..dafa951 100644
--- a/src/main/java/com/snp/batch/jobs/event/batch/writer/EventDataWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/event/writer/EventDataWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.event.batch.writer;
+package com.snp.batch.jobs.batch.event.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.event.batch.entity.EventDetailEntity;
-import com.snp.batch.jobs.event.batch.repository.EventRepository;
+import com.snp.batch.jobs.batch.event.entity.EventDetailEntity;
+import com.snp.batch.jobs.batch.event.repository.EventRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
diff --git a/src/main/java/com/snp/batch/jobs/facility/batch/config/PortImportJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/facility/config/PortImportJobConfig.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/facility/batch/config/PortImportJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/facility/config/PortImportJobConfig.java
index cf404e1..b5aa0dc 100644
--- a/src/main/java/com/snp/batch/jobs/facility/batch/config/PortImportJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/facility/config/PortImportJobConfig.java
@@ -1,11 +1,11 @@
-package com.snp.batch.jobs.facility.batch.config;
+package com.snp.batch.jobs.batch.facility.config;
import com.snp.batch.common.batch.config.BaseJobConfig;
-import com.snp.batch.jobs.facility.batch.dto.PortDto;
-import com.snp.batch.jobs.facility.batch.entity.PortEntity;
-import com.snp.batch.jobs.facility.batch.processor.PortDataProcessor;
-import com.snp.batch.jobs.facility.batch.reader.PortDataReader;
-import com.snp.batch.jobs.facility.batch.writer.PortDataWriter;
+import com.snp.batch.jobs.batch.facility.dto.PortDto;
+import com.snp.batch.jobs.batch.facility.entity.PortEntity;
+import com.snp.batch.jobs.batch.facility.processor.PortDataProcessor;
+import com.snp.batch.jobs.batch.facility.reader.PortDataReader;
+import com.snp.batch.jobs.batch.facility.writer.PortDataWriter;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
diff --git a/src/main/java/com/snp/batch/jobs/facility/batch/dto/PortDto.java b/src/main/java/com/snp/batch/jobs/batch/facility/dto/PortDto.java
similarity index 98%
rename from src/main/java/com/snp/batch/jobs/facility/batch/dto/PortDto.java
rename to src/main/java/com/snp/batch/jobs/batch/facility/dto/PortDto.java
index f324028..8789e29 100644
--- a/src/main/java/com/snp/batch/jobs/facility/batch/dto/PortDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/facility/dto/PortDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.facility.batch.dto;
+package com.snp.batch.jobs.batch.facility.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/facility/batch/dto/PortResponse.java b/src/main/java/com/snp/batch/jobs/batch/facility/dto/PortResponse.java
similarity index 84%
rename from src/main/java/com/snp/batch/jobs/facility/batch/dto/PortResponse.java
rename to src/main/java/com/snp/batch/jobs/batch/facility/dto/PortResponse.java
index 99918db..4a85a4c 100644
--- a/src/main/java/com/snp/batch/jobs/facility/batch/dto/PortResponse.java
+++ b/src/main/java/com/snp/batch/jobs/batch/facility/dto/PortResponse.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.facility.batch.dto;
+package com.snp.batch.jobs.batch.facility.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
diff --git a/src/main/java/com/snp/batch/jobs/facility/batch/entity/PortEntity.java b/src/main/java/com/snp/batch/jobs/batch/facility/entity/PortEntity.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/facility/batch/entity/PortEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/facility/entity/PortEntity.java
index b4b7875..49e08be 100644
--- a/src/main/java/com/snp/batch/jobs/facility/batch/entity/PortEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/facility/entity/PortEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.facility.batch.entity;
+package com.snp.batch.jobs.batch.facility.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import jakarta.persistence.Embedded;
diff --git a/src/main/java/com/snp/batch/jobs/facility/batch/processor/PortDataProcessor.java b/src/main/java/com/snp/batch/jobs/batch/facility/processor/PortDataProcessor.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/facility/batch/processor/PortDataProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/facility/processor/PortDataProcessor.java
index 391c264..9f5fcac 100644
--- a/src/main/java/com/snp/batch/jobs/facility/batch/processor/PortDataProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/facility/processor/PortDataProcessor.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.facility.batch.processor;
+package com.snp.batch.jobs.batch.facility.processor;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.facility.batch.dto.PortDto;
-import com.snp.batch.jobs.facility.batch.entity.PortEntity;
+import com.snp.batch.jobs.batch.facility.dto.PortDto;
+import com.snp.batch.jobs.batch.facility.entity.PortEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/facility/batch/reader/PortDataReader.java b/src/main/java/com/snp/batch/jobs/batch/facility/reader/PortDataReader.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/facility/batch/reader/PortDataReader.java
rename to src/main/java/com/snp/batch/jobs/batch/facility/reader/PortDataReader.java
index 26cf8f9..aaff25a 100644
--- a/src/main/java/com/snp/batch/jobs/facility/batch/reader/PortDataReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/facility/reader/PortDataReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.facility.batch.reader;
+package com.snp.batch.jobs.batch.facility.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.facility.batch.dto.PortDto;
+import com.snp.batch.jobs.batch.facility.dto.PortDto;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
diff --git a/src/main/java/com/snp/batch/jobs/batch/facility/repository/FacilityRepository.java b/src/main/java/com/snp/batch/jobs/batch/facility/repository/FacilityRepository.java
new file mode 100644
index 0000000..7e7223f
--- /dev/null
+++ b/src/main/java/com/snp/batch/jobs/batch/facility/repository/FacilityRepository.java
@@ -0,0 +1,9 @@
+package com.snp.batch.jobs.batch.facility.repository;
+
+import com.snp.batch.jobs.batch.facility.entity.PortEntity;
+
+import java.util.List;
+
+public interface FacilityRepository {
+ void savePortAll(List items);
+}
diff --git a/src/main/java/com/snp/batch/jobs/facility/batch/repository/FacilityRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/facility/repository/FacilityRepositoryImpl.java
similarity index 98%
rename from src/main/java/com/snp/batch/jobs/facility/batch/repository/FacilityRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/facility/repository/FacilityRepositoryImpl.java
index b06eeab..105803b 100644
--- a/src/main/java/com/snp/batch/jobs/facility/batch/repository/FacilityRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/facility/repository/FacilityRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.facility.batch.repository;
+package com.snp.batch.jobs.batch.facility.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.facility.batch.entity.PortEntity;
+import com.snp.batch.jobs.batch.facility.entity.PortEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/facility/batch/writer/PortDataWriter.java b/src/main/java/com/snp/batch/jobs/batch/facility/writer/PortDataWriter.java
similarity index 79%
rename from src/main/java/com/snp/batch/jobs/facility/batch/writer/PortDataWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/facility/writer/PortDataWriter.java
index 2ddafcd..7e2984d 100644
--- a/src/main/java/com/snp/batch/jobs/facility/batch/writer/PortDataWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/facility/writer/PortDataWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.facility.batch.writer;
+package com.snp.batch.jobs.batch.facility.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.facility.batch.entity.PortEntity;
-import com.snp.batch.jobs.facility.batch.repository.FacilityRepository;
+import com.snp.batch.jobs.batch.facility.entity.PortEntity;
+import com.snp.batch.jobs.batch.facility.repository.FacilityRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/imometa/batch/config/ImoMetaImportJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/imometa/config/ImoMetaImportJobConfig.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/imometa/batch/config/ImoMetaImportJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/imometa/config/ImoMetaImportJobConfig.java
index bb17920..edf7387 100644
--- a/src/main/java/com/snp/batch/jobs/imometa/batch/config/ImoMetaImportJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/imometa/config/ImoMetaImportJobConfig.java
@@ -1,13 +1,13 @@
-package com.snp.batch.jobs.imometa.batch.config;
+package com.snp.batch.jobs.batch.imometa.config;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.global.model.BatchApiLog;
-import com.snp.batch.jobs.imometa.batch.dto.ImoMetaDto;
-import com.snp.batch.jobs.imometa.batch.dto.ImoMetaResponse;
-import com.snp.batch.jobs.imometa.batch.entity.ImoMetaEntity;
-import com.snp.batch.jobs.imometa.batch.reader.ImoMetaDataReader;
-import com.snp.batch.jobs.imometa.batch.repository.ImoMetaRepository;
-import com.snp.batch.jobs.imometa.batch.writer.ImoMetaDataWriter;
+import com.snp.batch.jobs.batch.imometa.dto.ImoMetaDto;
+import com.snp.batch.jobs.batch.imometa.dto.ImoMetaResponse;
+import com.snp.batch.jobs.batch.imometa.entity.ImoMetaEntity;
+import com.snp.batch.jobs.batch.imometa.reader.ImoMetaDataReader;
+import com.snp.batch.jobs.batch.imometa.repository.ImoMetaRepository;
+import com.snp.batch.jobs.batch.imometa.writer.ImoMetaDataWriter;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
diff --git a/src/main/java/com/snp/batch/jobs/imometa/batch/dto/ImoMetaDto.java b/src/main/java/com/snp/batch/jobs/batch/imometa/dto/ImoMetaDto.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/imometa/batch/dto/ImoMetaDto.java
rename to src/main/java/com/snp/batch/jobs/batch/imometa/dto/ImoMetaDto.java
index 68ddae6..9f43b94 100644
--- a/src/main/java/com/snp/batch/jobs/imometa/batch/dto/ImoMetaDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/imometa/dto/ImoMetaDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.imometa.batch.dto;
+package com.snp.batch.jobs.batch.imometa.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/imometa/batch/dto/ImoMetaResponse.java b/src/main/java/com/snp/batch/jobs/batch/imometa/dto/ImoMetaResponse.java
similarity index 88%
rename from src/main/java/com/snp/batch/jobs/imometa/batch/dto/ImoMetaResponse.java
rename to src/main/java/com/snp/batch/jobs/batch/imometa/dto/ImoMetaResponse.java
index 57245b1..d653d23 100644
--- a/src/main/java/com/snp/batch/jobs/imometa/batch/dto/ImoMetaResponse.java
+++ b/src/main/java/com/snp/batch/jobs/batch/imometa/dto/ImoMetaResponse.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.imometa.batch.dto;
+package com.snp.batch.jobs.batch.imometa.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/imometa/batch/entity/ImoMetaEntity.java b/src/main/java/com/snp/batch/jobs/batch/imometa/entity/ImoMetaEntity.java
similarity index 90%
rename from src/main/java/com/snp/batch/jobs/imometa/batch/entity/ImoMetaEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/imometa/entity/ImoMetaEntity.java
index b77dc9a..f7fdb65 100644
--- a/src/main/java/com/snp/batch/jobs/imometa/batch/entity/ImoMetaEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/imometa/entity/ImoMetaEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.imometa.batch.entity;
+package com.snp.batch.jobs.batch.imometa.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/imometa/batch/reader/ImoMetaDataReader.java b/src/main/java/com/snp/batch/jobs/batch/imometa/reader/ImoMetaDataReader.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/imometa/batch/reader/ImoMetaDataReader.java
rename to src/main/java/com/snp/batch/jobs/batch/imometa/reader/ImoMetaDataReader.java
index 3703c03..31d50cf 100644
--- a/src/main/java/com/snp/batch/jobs/imometa/batch/reader/ImoMetaDataReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/imometa/reader/ImoMetaDataReader.java
@@ -1,9 +1,9 @@
-package com.snp.batch.jobs.imometa.batch.reader;
+package com.snp.batch.jobs.batch.imometa.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
import com.snp.batch.global.model.BatchApiLog;
-import com.snp.batch.jobs.imometa.batch.dto.ImoMetaDto;
-import com.snp.batch.jobs.imometa.batch.dto.ImoMetaResponse;
+import com.snp.batch.jobs.batch.imometa.dto.ImoMetaDto;
+import com.snp.batch.jobs.batch.imometa.dto.ImoMetaResponse;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.reactive.function.client.WebClient;
diff --git a/src/main/java/com/snp/batch/jobs/imometa/batch/repository/ImoMetaRepository.java b/src/main/java/com/snp/batch/jobs/batch/imometa/repository/ImoMetaRepository.java
similarity index 58%
rename from src/main/java/com/snp/batch/jobs/imometa/batch/repository/ImoMetaRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/imometa/repository/ImoMetaRepository.java
index ee6edef..6f39731 100644
--- a/src/main/java/com/snp/batch/jobs/imometa/batch/repository/ImoMetaRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/imometa/repository/ImoMetaRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.imometa.batch.repository;
+package com.snp.batch.jobs.batch.imometa.repository;
-import com.snp.batch.jobs.imometa.batch.entity.ImoMetaEntity;
+import com.snp.batch.jobs.batch.imometa.entity.ImoMetaEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/imometa/batch/repository/ImoMetaRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/imometa/repository/ImoMetaRepositoryImpl.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/imometa/batch/repository/ImoMetaRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/imometa/repository/ImoMetaRepositoryImpl.java
index 9857ebd..826c507 100644
--- a/src/main/java/com/snp/batch/jobs/imometa/batch/repository/ImoMetaRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/imometa/repository/ImoMetaRepositoryImpl.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.imometa.batch.repository;
+package com.snp.batch.jobs.batch.imometa.repository;
-import com.snp.batch.jobs.imometa.batch.entity.ImoMetaEntity;
+import com.snp.batch.jobs.batch.imometa.entity.ImoMetaEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/imometa/batch/writer/ImoMetaDataWriter.java b/src/main/java/com/snp/batch/jobs/batch/imometa/writer/ImoMetaDataWriter.java
similarity index 77%
rename from src/main/java/com/snp/batch/jobs/imometa/batch/writer/ImoMetaDataWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/imometa/writer/ImoMetaDataWriter.java
index 2ebc1be..9d5de26 100644
--- a/src/main/java/com/snp/batch/jobs/imometa/batch/writer/ImoMetaDataWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/imometa/writer/ImoMetaDataWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.imometa.batch.writer;
+package com.snp.batch.jobs.batch.imometa.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.imometa.batch.entity.ImoMetaEntity;
-import com.snp.batch.jobs.imometa.batch.repository.ImoMetaRepository;
+import com.snp.batch.jobs.batch.imometa.entity.ImoMetaEntity;
+import com.snp.batch.jobs.batch.imometa.repository.ImoMetaRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/AnchorageCallsRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/movement/config/AnchorageCallsRangeJobConfig.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/movement/batch/config/AnchorageCallsRangeJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/config/AnchorageCallsRangeJobConfig.java
index 55f5605..246d1e6 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/config/AnchorageCallsRangeJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/config/AnchorageCallsRangeJobConfig.java
@@ -1,13 +1,13 @@
-package com.snp.batch.jobs.movement.batch.config;
+package com.snp.batch.jobs.batch.movement.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.movement.batch.dto.AnchorageCallsDto;
-import com.snp.batch.jobs.movement.batch.entity.AnchorageCallsEntity;
-import com.snp.batch.jobs.movement.batch.processor.AnchorageCallsProcessor;
-import com.snp.batch.jobs.movement.batch.reader.AnchorageCallsRangeReader;
-import com.snp.batch.jobs.movement.batch.writer.AnchorageCallsWriter;
+import com.snp.batch.jobs.batch.movement.dto.AnchorageCallsDto;
+import com.snp.batch.jobs.batch.movement.entity.AnchorageCallsEntity;
+import com.snp.batch.jobs.batch.movement.processor.AnchorageCallsProcessor;
+import com.snp.batch.jobs.batch.movement.reader.AnchorageCallsRangeReader;
+import com.snp.batch.jobs.batch.movement.writer.AnchorageCallsWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/BerthCallsRangJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/movement/config/BerthCallsRangJobConfig.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/config/BerthCallsRangJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/config/BerthCallsRangJobConfig.java
index e2c99cc..eb30f20 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/config/BerthCallsRangJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/config/BerthCallsRangJobConfig.java
@@ -1,13 +1,13 @@
-package com.snp.batch.jobs.movement.batch.config;
+package com.snp.batch.jobs.batch.movement.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.movement.batch.dto.BerthCallsDto;
-import com.snp.batch.jobs.movement.batch.entity.BerthCallsEntity;
-import com.snp.batch.jobs.movement.batch.processor.BerthCallsProcessor;
-import com.snp.batch.jobs.movement.batch.reader.BerthCallsRangeReader;
-import com.snp.batch.jobs.movement.batch.writer.BerthCallsWriter;
+import com.snp.batch.jobs.batch.movement.dto.BerthCallsDto;
+import com.snp.batch.jobs.batch.movement.entity.BerthCallsEntity;
+import com.snp.batch.jobs.batch.movement.processor.BerthCallsProcessor;
+import com.snp.batch.jobs.batch.movement.reader.BerthCallsRangeReader;
+import com.snp.batch.jobs.batch.movement.writer.BerthCallsWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/CurrentlyAtRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/movement/config/CurrentlyAtRangeJobConfig.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/movement/batch/config/CurrentlyAtRangeJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/config/CurrentlyAtRangeJobConfig.java
index 5bb8621..226ccd6 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/config/CurrentlyAtRangeJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/config/CurrentlyAtRangeJobConfig.java
@@ -1,13 +1,13 @@
-package com.snp.batch.jobs.movement.batch.config;
+package com.snp.batch.jobs.batch.movement.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.movement.batch.dto.CurrentlyAtDto;
-import com.snp.batch.jobs.movement.batch.entity.CurrentlyAtEntity;
-import com.snp.batch.jobs.movement.batch.processor.CurrentlyAtProcessor;
-import com.snp.batch.jobs.movement.batch.reader.CurrentlyAtRangeReader;
-import com.snp.batch.jobs.movement.batch.writer.CurrentlyAtWriter;
+import com.snp.batch.jobs.batch.movement.dto.CurrentlyAtDto;
+import com.snp.batch.jobs.batch.movement.entity.CurrentlyAtEntity;
+import com.snp.batch.jobs.batch.movement.processor.CurrentlyAtProcessor;
+import com.snp.batch.jobs.batch.movement.reader.CurrentlyAtRangeReader;
+import com.snp.batch.jobs.batch.movement.writer.CurrentlyAtWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/DestinationsRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/movement/config/DestinationsRangeJobConfig.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/movement/batch/config/DestinationsRangeJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/config/DestinationsRangeJobConfig.java
index 9aa35ea..9e74c79 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/config/DestinationsRangeJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/config/DestinationsRangeJobConfig.java
@@ -1,13 +1,13 @@
-package com.snp.batch.jobs.movement.batch.config;
+package com.snp.batch.jobs.batch.movement.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.movement.batch.dto.DestinationDto;
-import com.snp.batch.jobs.movement.batch.entity.DestinationEntity;
-import com.snp.batch.jobs.movement.batch.processor.DestinationProcessor;
-import com.snp.batch.jobs.movement.batch.reader.DestinationRangeReader;
-import com.snp.batch.jobs.movement.batch.writer.DestinationWriter;
+import com.snp.batch.jobs.batch.movement.dto.DestinationDto;
+import com.snp.batch.jobs.batch.movement.entity.DestinationEntity;
+import com.snp.batch.jobs.batch.movement.processor.DestinationProcessor;
+import com.snp.batch.jobs.batch.movement.reader.DestinationRangeReader;
+import com.snp.batch.jobs.batch.movement.writer.DestinationWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/ShipPortCallsRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/movement/config/ShipPortCallsRangeJobConfig.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/config/ShipPortCallsRangeJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/config/ShipPortCallsRangeJobConfig.java
index 92ce464..7758b53 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/config/ShipPortCallsRangeJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/config/ShipPortCallsRangeJobConfig.java
@@ -1,13 +1,13 @@
-package com.snp.batch.jobs.movement.batch.config;
+package com.snp.batch.jobs.batch.movement.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.movement.batch.dto.PortCallsDto;
-import com.snp.batch.jobs.movement.batch.entity.PortCallsEntity;
-import com.snp.batch.jobs.movement.batch.processor.PortCallsProcessor;
-import com.snp.batch.jobs.movement.batch.reader.PortCallsRangeReader;
-import com.snp.batch.jobs.movement.batch.writer.PortCallsWriter;
+import com.snp.batch.jobs.batch.movement.dto.PortCallsDto;
+import com.snp.batch.jobs.batch.movement.entity.PortCallsEntity;
+import com.snp.batch.jobs.batch.movement.processor.PortCallsProcessor;
+import com.snp.batch.jobs.batch.movement.reader.PortCallsRangeReader;
+import com.snp.batch.jobs.batch.movement.writer.PortCallsWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/StsOperationRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/movement/config/StsOperationRangeJobConfig.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/movement/batch/config/StsOperationRangeJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/config/StsOperationRangeJobConfig.java
index 8b35c2a..93c388f 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/config/StsOperationRangeJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/config/StsOperationRangeJobConfig.java
@@ -1,13 +1,13 @@
-package com.snp.batch.jobs.movement.batch.config;
+package com.snp.batch.jobs.batch.movement.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.movement.batch.dto.StsOperationDto;
-import com.snp.batch.jobs.movement.batch.entity.StsOperationEntity;
-import com.snp.batch.jobs.movement.batch.processor.StsOperationProcessor;
-import com.snp.batch.jobs.movement.batch.reader.StsOperationRangeReader;
-import com.snp.batch.jobs.movement.batch.writer.StsOperationWriter;
+import com.snp.batch.jobs.batch.movement.dto.StsOperationDto;
+import com.snp.batch.jobs.batch.movement.entity.StsOperationEntity;
+import com.snp.batch.jobs.batch.movement.processor.StsOperationProcessor;
+import com.snp.batch.jobs.batch.movement.reader.StsOperationRangeReader;
+import com.snp.batch.jobs.batch.movement.writer.StsOperationWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/TerminalCallsRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/movement/config/TerminalCallsRangeJobConfig.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/movement/batch/config/TerminalCallsRangeJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/config/TerminalCallsRangeJobConfig.java
index 59f006a..bbc2f8a 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/config/TerminalCallsRangeJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/config/TerminalCallsRangeJobConfig.java
@@ -1,13 +1,13 @@
-package com.snp.batch.jobs.movement.batch.config;
+package com.snp.batch.jobs.batch.movement.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.movement.batch.dto.TerminalCallsDto;
-import com.snp.batch.jobs.movement.batch.entity.TerminalCallsEntity;
-import com.snp.batch.jobs.movement.batch.processor.TerminalCallsProcessor;
-import com.snp.batch.jobs.movement.batch.reader.TerminalCallsRangeReader;
-import com.snp.batch.jobs.movement.batch.writer.TerminalCallsWriter;
+import com.snp.batch.jobs.batch.movement.dto.TerminalCallsDto;
+import com.snp.batch.jobs.batch.movement.entity.TerminalCallsEntity;
+import com.snp.batch.jobs.batch.movement.processor.TerminalCallsProcessor;
+import com.snp.batch.jobs.batch.movement.reader.TerminalCallsRangeReader;
+import com.snp.batch.jobs.batch.movement.writer.TerminalCallsWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/TransitsRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/movement/config/TransitsRangeJobConfig.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/config/TransitsRangeJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/config/TransitsRangeJobConfig.java
index de521cd..b8b2a14 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/config/TransitsRangeJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/config/TransitsRangeJobConfig.java
@@ -1,12 +1,12 @@
-package com.snp.batch.jobs.movement.batch.config;
+package com.snp.batch.jobs.batch.movement.config;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.movement.batch.dto.TransitsDto;
-import com.snp.batch.jobs.movement.batch.entity.TransitsEntity;
-import com.snp.batch.jobs.movement.batch.processor.TransitsProcessor;
-import com.snp.batch.jobs.movement.batch.reader.TransitsRangeReader;
-import com.snp.batch.jobs.movement.batch.writer.TransitsWriter;
+import com.snp.batch.jobs.batch.movement.dto.TransitsDto;
+import com.snp.batch.jobs.batch.movement.entity.TransitsEntity;
+import com.snp.batch.jobs.batch.movement.processor.TransitsProcessor;
+import com.snp.batch.jobs.batch.movement.reader.TransitsRangeReader;
+import com.snp.batch.jobs.batch.movement.writer.TransitsWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/AnchorageCallsDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/AnchorageCallsDto.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/AnchorageCallsDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/AnchorageCallsDto.java
index 0d4e885..f345154 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/AnchorageCallsDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/AnchorageCallsDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/AnchorageCallsPositionDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/AnchorageCallsPositionDto.java
similarity index 89%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/AnchorageCallsPositionDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/AnchorageCallsPositionDto.java
index 419eb7d..856e271 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/AnchorageCallsPositionDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/AnchorageCallsPositionDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/BerthCallsDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/BerthCallsDto.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/BerthCallsDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/BerthCallsDto.java
index d133f60..e02a726 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/BerthCallsDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/BerthCallsDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/BerthCallsPositionDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/BerthCallsPositionDto.java
similarity index 87%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/BerthCallsPositionDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/BerthCallsPositionDto.java
index 365cce3..73087d7 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/BerthCallsPositionDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/BerthCallsPositionDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/CurrentlyAtDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/CurrentlyAtDto.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/CurrentlyAtDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/CurrentlyAtDto.java
index 7cdc0a9..22d2728 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/CurrentlyAtDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/CurrentlyAtDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/CurrentlyAtPositionDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/CurrentlyAtPositionDto.java
similarity index 87%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/CurrentlyAtPositionDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/CurrentlyAtPositionDto.java
index 96e8b1b..633def4 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/CurrentlyAtPositionDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/CurrentlyAtPositionDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/DestinationDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/DestinationDto.java
similarity index 90%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/DestinationDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/DestinationDto.java
index ff5804e..b0aaa71 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/DestinationDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/DestinationDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/DestinationPositionDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/DestinationPositionDto.java
similarity index 87%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/DestinationPositionDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/DestinationPositionDto.java
index d9f5d28..33380b4 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/DestinationPositionDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/DestinationPositionDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/PortCallsDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/PortCallsDto.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/PortCallsDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/PortCallsDto.java
index f67a702..d8134dc 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/PortCallsDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/PortCallsDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/PortCallsPositionDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/PortCallsPositionDto.java
similarity index 87%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/PortCallsPositionDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/PortCallsPositionDto.java
index fa1e531..ecb13d8 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/PortCallsPositionDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/PortCallsPositionDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/ShipMovementApiResponse.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/ShipMovementApiResponse.java
similarity index 82%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/ShipMovementApiResponse.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/ShipMovementApiResponse.java
index f1464ef..c12d407 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/ShipMovementApiResponse.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/ShipMovementApiResponse.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/StsOperationDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/StsOperationDto.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/StsOperationDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/StsOperationDto.java
index 4318ec3..4b1c9c4 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/StsOperationDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/StsOperationDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/StsOperationPositionDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/StsOperationPositionDto.java
similarity index 88%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/StsOperationPositionDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/StsOperationPositionDto.java
index 4410970..d6bbf9c 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/StsOperationPositionDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/StsOperationPositionDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/TerminalCallsDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/TerminalCallsDto.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/TerminalCallsDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/TerminalCallsDto.java
index 12281e6..6c5cbfe 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/TerminalCallsDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/TerminalCallsDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/TerminalCallsPositionDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/TerminalCallsPositionDto.java
similarity index 88%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/TerminalCallsPositionDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/TerminalCallsPositionDto.java
index 1179f09..33b857d 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/TerminalCallsPositionDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/TerminalCallsPositionDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/dto/TransitsDto.java b/src/main/java/com/snp/batch/jobs/batch/movement/dto/TransitsDto.java
similarity index 84%
rename from src/main/java/com/snp/batch/jobs/movement/batch/dto/TransitsDto.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/dto/TransitsDto.java
index d3351b9..4e613f7 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/dto/TransitsDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/dto/TransitsDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.dto;
+package com.snp.batch.jobs.batch.movement.dto;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/entity/AnchorageCallsEntity.java b/src/main/java/com/snp/batch/jobs/batch/movement/entity/AnchorageCallsEntity.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/movement/batch/entity/AnchorageCallsEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/entity/AnchorageCallsEntity.java
index c21cbfd..8eee6dd 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/entity/AnchorageCallsEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/entity/AnchorageCallsEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.entity;
+package com.snp.batch.jobs.batch.movement.entity;
import com.fasterxml.jackson.databind.JsonNode;
import com.snp.batch.common.batch.entity.BaseEntity;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/entity/BerthCallsEntity.java b/src/main/java/com/snp/batch/jobs/batch/movement/entity/BerthCallsEntity.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/movement/batch/entity/BerthCallsEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/entity/BerthCallsEntity.java
index 5553e94..35749a7 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/entity/BerthCallsEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/entity/BerthCallsEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.entity;
+package com.snp.batch.jobs.batch.movement.entity;
import com.fasterxml.jackson.databind.JsonNode;
import com.snp.batch.common.batch.entity.BaseEntity;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/entity/CurrentlyAtEntity.java b/src/main/java/com/snp/batch/jobs/batch/movement/entity/CurrentlyAtEntity.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/movement/batch/entity/CurrentlyAtEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/entity/CurrentlyAtEntity.java
index 5b5c60a..7ba34cf 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/entity/CurrentlyAtEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/entity/CurrentlyAtEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.entity;
+package com.snp.batch.jobs.batch.movement.entity;
import com.fasterxml.jackson.databind.JsonNode;
import com.snp.batch.common.batch.entity.BaseEntity;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/entity/DestinationEntity.java b/src/main/java/com/snp/batch/jobs/batch/movement/entity/DestinationEntity.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/movement/batch/entity/DestinationEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/entity/DestinationEntity.java
index 3395baa..7ed8a3d 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/entity/DestinationEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/entity/DestinationEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.entity;
+package com.snp.batch.jobs.batch.movement.entity;
import com.fasterxml.jackson.databind.JsonNode;
import com.snp.batch.common.batch.entity.BaseEntity;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/entity/PortCallsEntity.java b/src/main/java/com/snp/batch/jobs/batch/movement/entity/PortCallsEntity.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/movement/batch/entity/PortCallsEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/entity/PortCallsEntity.java
index 651265a..f2735a7 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/entity/PortCallsEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/entity/PortCallsEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.entity;
+package com.snp.batch.jobs.batch.movement.entity;
import com.fasterxml.jackson.databind.JsonNode;
import com.snp.batch.common.batch.entity.BaseEntity;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/entity/StsOperationEntity.java b/src/main/java/com/snp/batch/jobs/batch/movement/entity/StsOperationEntity.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/movement/batch/entity/StsOperationEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/entity/StsOperationEntity.java
index 81df3cf..c645a27 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/entity/StsOperationEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/entity/StsOperationEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.entity;
+package com.snp.batch.jobs.batch.movement.entity;
import com.fasterxml.jackson.databind.JsonNode;
import com.snp.batch.common.batch.entity.BaseEntity;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/entity/TerminalCallsEntity.java b/src/main/java/com/snp/batch/jobs/batch/movement/entity/TerminalCallsEntity.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/movement/batch/entity/TerminalCallsEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/entity/TerminalCallsEntity.java
index bb68aae..0211cb8 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/entity/TerminalCallsEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/entity/TerminalCallsEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.entity;
+package com.snp.batch.jobs.batch.movement.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/entity/TransitsEntity.java b/src/main/java/com/snp/batch/jobs/batch/movement/entity/TransitsEntity.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/movement/batch/entity/TransitsEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/entity/TransitsEntity.java
index cddbad6..2d3ef25 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/entity/TransitsEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/entity/TransitsEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.movement.batch.entity;
+package com.snp.batch.jobs.batch.movement.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/processor/AnchorageCallsProcessor.java b/src/main/java/com/snp/batch/jobs/batch/movement/processor/AnchorageCallsProcessor.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/processor/AnchorageCallsProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/processor/AnchorageCallsProcessor.java
index bd560dd..4174813 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/processor/AnchorageCallsProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/processor/AnchorageCallsProcessor.java
@@ -1,10 +1,10 @@
-package com.snp.batch.jobs.movement.batch.processor;
+package com.snp.batch.jobs.batch.movement.processor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.movement.batch.dto.AnchorageCallsDto;
-import com.snp.batch.jobs.movement.batch.entity.AnchorageCallsEntity;
+import com.snp.batch.jobs.batch.movement.dto.AnchorageCallsDto;
+import com.snp.batch.jobs.batch.movement.entity.AnchorageCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/processor/BerthCallsProcessor.java b/src/main/java/com/snp/batch/jobs/batch/movement/processor/BerthCallsProcessor.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/processor/BerthCallsProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/processor/BerthCallsProcessor.java
index 0b2a52f..7225e2b 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/processor/BerthCallsProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/processor/BerthCallsProcessor.java
@@ -1,10 +1,10 @@
-package com.snp.batch.jobs.movement.batch.processor;
+package com.snp.batch.jobs.batch.movement.processor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.movement.batch.dto.BerthCallsDto;
-import com.snp.batch.jobs.movement.batch.entity.BerthCallsEntity;
+import com.snp.batch.jobs.batch.movement.dto.BerthCallsDto;
+import com.snp.batch.jobs.batch.movement.entity.BerthCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/processor/CurrentlyAtProcessor.java b/src/main/java/com/snp/batch/jobs/batch/movement/processor/CurrentlyAtProcessor.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/processor/CurrentlyAtProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/processor/CurrentlyAtProcessor.java
index f72b369..8cf0a11 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/processor/CurrentlyAtProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/processor/CurrentlyAtProcessor.java
@@ -1,10 +1,10 @@
-package com.snp.batch.jobs.movement.batch.processor;
+package com.snp.batch.jobs.batch.movement.processor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.movement.batch.dto.CurrentlyAtDto;
-import com.snp.batch.jobs.movement.batch.entity.CurrentlyAtEntity;
+import com.snp.batch.jobs.batch.movement.dto.CurrentlyAtDto;
+import com.snp.batch.jobs.batch.movement.entity.CurrentlyAtEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/processor/DestinationProcessor.java b/src/main/java/com/snp/batch/jobs/batch/movement/processor/DestinationProcessor.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/movement/batch/processor/DestinationProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/processor/DestinationProcessor.java
index b6e085c..763c167 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/processor/DestinationProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/processor/DestinationProcessor.java
@@ -1,10 +1,10 @@
-package com.snp.batch.jobs.movement.batch.processor;
+package com.snp.batch.jobs.batch.movement.processor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.movement.batch.dto.DestinationDto;
-import com.snp.batch.jobs.movement.batch.entity.DestinationEntity;
+import com.snp.batch.jobs.batch.movement.dto.DestinationDto;
+import com.snp.batch.jobs.batch.movement.entity.DestinationEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/processor/PortCallsProcessor.java b/src/main/java/com/snp/batch/jobs/batch/movement/processor/PortCallsProcessor.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/processor/PortCallsProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/processor/PortCallsProcessor.java
index 52d518d..c767899 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/processor/PortCallsProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/processor/PortCallsProcessor.java
@@ -1,10 +1,10 @@
-package com.snp.batch.jobs.movement.batch.processor;
+package com.snp.batch.jobs.batch.movement.processor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.movement.batch.dto.PortCallsDto;
-import com.snp.batch.jobs.movement.batch.entity.PortCallsEntity;
+import com.snp.batch.jobs.batch.movement.dto.PortCallsDto;
+import com.snp.batch.jobs.batch.movement.entity.PortCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/processor/StsOperationProcessor.java b/src/main/java/com/snp/batch/jobs/batch/movement/processor/StsOperationProcessor.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/processor/StsOperationProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/processor/StsOperationProcessor.java
index 3f2fc9c..020f56d 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/processor/StsOperationProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/processor/StsOperationProcessor.java
@@ -1,10 +1,10 @@
-package com.snp.batch.jobs.movement.batch.processor;
+package com.snp.batch.jobs.batch.movement.processor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.movement.batch.dto.StsOperationDto;
-import com.snp.batch.jobs.movement.batch.entity.StsOperationEntity;
+import com.snp.batch.jobs.batch.movement.dto.StsOperationDto;
+import com.snp.batch.jobs.batch.movement.entity.StsOperationEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/processor/TerminalCallsProcessor.java b/src/main/java/com/snp/batch/jobs/batch/movement/processor/TerminalCallsProcessor.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/movement/batch/processor/TerminalCallsProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/processor/TerminalCallsProcessor.java
index 28bfa17..c8b686f 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/processor/TerminalCallsProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/processor/TerminalCallsProcessor.java
@@ -1,10 +1,10 @@
-package com.snp.batch.jobs.movement.batch.processor;
+package com.snp.batch.jobs.batch.movement.processor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.movement.batch.dto.TerminalCallsDto;
-import com.snp.batch.jobs.movement.batch.entity.TerminalCallsEntity;
+import com.snp.batch.jobs.batch.movement.dto.TerminalCallsDto;
+import com.snp.batch.jobs.batch.movement.entity.TerminalCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/processor/TransitsProcessor.java b/src/main/java/com/snp/batch/jobs/batch/movement/processor/TransitsProcessor.java
similarity index 88%
rename from src/main/java/com/snp/batch/jobs/movement/batch/processor/TransitsProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/processor/TransitsProcessor.java
index 199b9f3..059bbe9 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/processor/TransitsProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/processor/TransitsProcessor.java
@@ -1,9 +1,9 @@
-package com.snp.batch.jobs.movement.batch.processor;
+package com.snp.batch.jobs.batch.movement.processor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.movement.batch.dto.TransitsDto;
-import com.snp.batch.jobs.movement.batch.entity.TransitsEntity;
+import com.snp.batch.jobs.batch.movement.dto.TransitsDto;
+import com.snp.batch.jobs.batch.movement.entity.TransitsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/reader/AnchorageCallsRangeReader.java b/src/main/java/com/snp/batch/jobs/batch/movement/reader/AnchorageCallsRangeReader.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/reader/AnchorageCallsRangeReader.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/reader/AnchorageCallsRangeReader.java
index bf0fd8d..82fc637 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/reader/AnchorageCallsRangeReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/reader/AnchorageCallsRangeReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.movement.batch.reader;
+package com.snp.batch.jobs.batch.movement.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.movement.batch.dto.AnchorageCallsDto;
+import com.snp.batch.jobs.batch.movement.dto.AnchorageCallsDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/reader/BerthCallsRangeReader.java b/src/main/java/com/snp/batch/jobs/batch/movement/reader/BerthCallsRangeReader.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/reader/BerthCallsRangeReader.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/reader/BerthCallsRangeReader.java
index a742932..ecccd69 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/reader/BerthCallsRangeReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/reader/BerthCallsRangeReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.movement.batch.reader;
+package com.snp.batch.jobs.batch.movement.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.movement.batch.dto.BerthCallsDto;
+import com.snp.batch.jobs.batch.movement.dto.BerthCallsDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/reader/CurrentlyAtRangeReader.java b/src/main/java/com/snp/batch/jobs/batch/movement/reader/CurrentlyAtRangeReader.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/reader/CurrentlyAtRangeReader.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/reader/CurrentlyAtRangeReader.java
index 0827855..bc28678 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/reader/CurrentlyAtRangeReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/reader/CurrentlyAtRangeReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.movement.batch.reader;
+package com.snp.batch.jobs.batch.movement.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.movement.batch.dto.CurrentlyAtDto;
+import com.snp.batch.jobs.batch.movement.dto.CurrentlyAtDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/reader/DestinationRangeReader.java b/src/main/java/com/snp/batch/jobs/batch/movement/reader/DestinationRangeReader.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/reader/DestinationRangeReader.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/reader/DestinationRangeReader.java
index 2c43ec0..de8f560 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/reader/DestinationRangeReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/reader/DestinationRangeReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.movement.batch.reader;
+package com.snp.batch.jobs.batch.movement.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.movement.batch.dto.DestinationDto;
+import com.snp.batch.jobs.batch.movement.dto.DestinationDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/reader/PortCallsRangeReader.java b/src/main/java/com/snp/batch/jobs/batch/movement/reader/PortCallsRangeReader.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/reader/PortCallsRangeReader.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/reader/PortCallsRangeReader.java
index aad0ebf..9b76f32 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/reader/PortCallsRangeReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/reader/PortCallsRangeReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.movement.batch.reader;
+package com.snp.batch.jobs.batch.movement.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.movement.batch.dto.PortCallsDto;
+import com.snp.batch.jobs.batch.movement.dto.PortCallsDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/reader/StsOperationRangeReader.java b/src/main/java/com/snp/batch/jobs/batch/movement/reader/StsOperationRangeReader.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/reader/StsOperationRangeReader.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/reader/StsOperationRangeReader.java
index b3640bf..fd52d8b 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/reader/StsOperationRangeReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/reader/StsOperationRangeReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.movement.batch.reader;
+package com.snp.batch.jobs.batch.movement.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.movement.batch.dto.StsOperationDto;
+import com.snp.batch.jobs.batch.movement.dto.StsOperationDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/reader/TerminalCallsRangeReader.java b/src/main/java/com/snp/batch/jobs/batch/movement/reader/TerminalCallsRangeReader.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/reader/TerminalCallsRangeReader.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/reader/TerminalCallsRangeReader.java
index 49e7704..c388b12 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/reader/TerminalCallsRangeReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/reader/TerminalCallsRangeReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.movement.batch.reader;
+package com.snp.batch.jobs.batch.movement.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.movement.batch.dto.TerminalCallsDto;
+import com.snp.batch.jobs.batch.movement.dto.TerminalCallsDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/reader/TransitsRangeReader.java b/src/main/java/com/snp/batch/jobs/batch/movement/reader/TransitsRangeReader.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/movement/batch/reader/TransitsRangeReader.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/reader/TransitsRangeReader.java
index b2475be..def5cce 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/reader/TransitsRangeReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/reader/TransitsRangeReader.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.reader;
+package com.snp.batch.jobs.batch.movement.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.movement.batch.dto.AnchorageCallsDto;
-import com.snp.batch.jobs.movement.batch.dto.TransitsDto;
+import com.snp.batch.jobs.batch.movement.dto.AnchorageCallsDto;
+import com.snp.batch.jobs.batch.movement.dto.TransitsDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/AnchorageCallsRepository.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/AnchorageCallsRepository.java
similarity index 62%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/AnchorageCallsRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/AnchorageCallsRepository.java
index 7101a51..4a7d613 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/AnchorageCallsRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/AnchorageCallsRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
-import com.snp.batch.jobs.movement.batch.entity.AnchorageCallsEntity;
+import com.snp.batch.jobs.batch.movement.entity.AnchorageCallsEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/AnchorageCallsRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/AnchorageCallsRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/AnchorageCallsRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/AnchorageCallsRepositoryImpl.java
index 631fe6a..8600f22 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/AnchorageCallsRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/AnchorageCallsRepositoryImpl.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.movement.batch.entity.AnchorageCallsEntity;
+import com.snp.batch.jobs.batch.movement.entity.AnchorageCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/BerthCallsRepository.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/BerthCallsRepository.java
similarity index 60%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/BerthCallsRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/BerthCallsRepository.java
index b501ac6..8914f3a 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/BerthCallsRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/BerthCallsRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
-import com.snp.batch.jobs.movement.batch.entity.BerthCallsEntity;
+import com.snp.batch.jobs.batch.movement.entity.BerthCallsEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/BerthCallsRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/BerthCallsRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/BerthCallsRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/BerthCallsRepositoryImpl.java
index d2db18c..0c3a39d 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/BerthCallsRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/BerthCallsRepositoryImpl.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.movement.batch.entity.BerthCallsEntity;
+import com.snp.batch.jobs.batch.movement.entity.BerthCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/CurrentlyAtRepository.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/CurrentlyAtRepository.java
similarity index 60%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/CurrentlyAtRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/CurrentlyAtRepository.java
index 5f105c0..24489de 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/CurrentlyAtRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/CurrentlyAtRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
-import com.snp.batch.jobs.movement.batch.entity.CurrentlyAtEntity;
+import com.snp.batch.jobs.batch.movement.entity.CurrentlyAtEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/CurrentlyAtRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/CurrentlyAtRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/CurrentlyAtRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/CurrentlyAtRepositoryImpl.java
index 57851c5..b7702ff 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/CurrentlyAtRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/CurrentlyAtRepositoryImpl.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.movement.batch.entity.CurrentlyAtEntity;
+import com.snp.batch.jobs.batch.movement.entity.CurrentlyAtEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/DestinationRepository.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/DestinationRepository.java
similarity index 60%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/DestinationRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/DestinationRepository.java
index 0bc014c..2b5d933 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/DestinationRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/DestinationRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
-import com.snp.batch.jobs.movement.batch.entity.DestinationEntity;
+import com.snp.batch.jobs.batch.movement.entity.DestinationEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/DestinationRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/DestinationRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/DestinationRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/DestinationRepositoryImpl.java
index e766a67..432831f 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/DestinationRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/DestinationRepositoryImpl.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.movement.batch.entity.DestinationEntity;
+import com.snp.batch.jobs.batch.movement.entity.DestinationEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/PortCallsRepository.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/PortCallsRepository.java
similarity index 50%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/PortCallsRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/PortCallsRepository.java
index 9a7ab22..5e98851 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/PortCallsRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/PortCallsRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
-import com.snp.batch.jobs.movement.batch.entity.PortCallsEntity;
+import com.snp.batch.jobs.batch.movement.entity.PortCallsEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/PortCallsRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/PortCallsRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/PortCallsRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/PortCallsRepositoryImpl.java
index 9ff1123..c1897d2 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/PortCallsRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/PortCallsRepositoryImpl.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.movement.batch.entity.PortCallsEntity;
+import com.snp.batch.jobs.batch.movement.entity.PortCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/StsOperationRepository.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/StsOperationRepository.java
similarity index 61%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/StsOperationRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/StsOperationRepository.java
index c9abd34..a152598 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/StsOperationRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/StsOperationRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
-import com.snp.batch.jobs.movement.batch.entity.StsOperationEntity;
+import com.snp.batch.jobs.batch.movement.entity.StsOperationEntity;
import java.util.List;
/**
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/StsOperationRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/StsOperationRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/StsOperationRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/StsOperationRepositoryImpl.java
index d023cd7..d549c3f 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/StsOperationRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/StsOperationRepositoryImpl.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.movement.batch.entity.StsOperationEntity;
+import com.snp.batch.jobs.batch.movement.entity.StsOperationEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/TerminalCallsRepository.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/TerminalCallsRepository.java
similarity index 61%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/TerminalCallsRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/TerminalCallsRepository.java
index 71ee017..c25a436 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/TerminalCallsRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/TerminalCallsRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
-import com.snp.batch.jobs.movement.batch.entity.TerminalCallsEntity;
+import com.snp.batch.jobs.batch.movement.entity.TerminalCallsEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/TerminalCallsRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/TerminalCallsRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/TerminalCallsRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/TerminalCallsRepositoryImpl.java
index 38b7f23..bd6f55c 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/TerminalCallsRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/TerminalCallsRepositoryImpl.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.movement.batch.entity.TerminalCallsEntity;
+import com.snp.batch.jobs.batch.movement.entity.TerminalCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/TransitsRepository.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/TransitsRepository.java
similarity index 59%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/TransitsRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/TransitsRepository.java
index 235f3ef..679e629 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/TransitsRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/TransitsRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
-import com.snp.batch.jobs.movement.batch.entity.TransitsEntity;
+import com.snp.batch.jobs.batch.movement.entity.TransitsEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/repository/TransitsRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/movement/repository/TransitsRepositoryImpl.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/movement/batch/repository/TransitsRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/repository/TransitsRepositoryImpl.java
index f289162..24cc769 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/repository/TransitsRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/repository/TransitsRepositoryImpl.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.repository;
+package com.snp.batch.jobs.batch.movement.repository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.movement.batch.entity.TransitsEntity;
+import com.snp.batch.jobs.batch.movement.entity.TransitsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/writer/AnchorageCallsWriter.java b/src/main/java/com/snp/batch/jobs/batch/movement/writer/AnchorageCallsWriter.java
similarity index 82%
rename from src/main/java/com/snp/batch/jobs/movement/batch/writer/AnchorageCallsWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/writer/AnchorageCallsWriter.java
index b3600ab..4c33f8f 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/writer/AnchorageCallsWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/writer/AnchorageCallsWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.writer;
+package com.snp.batch.jobs.batch.movement.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.movement.batch.repository.AnchorageCallsRepository;
-import com.snp.batch.jobs.movement.batch.entity.AnchorageCallsEntity;
+import com.snp.batch.jobs.batch.movement.repository.AnchorageCallsRepository;
+import com.snp.batch.jobs.batch.movement.entity.AnchorageCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/writer/BerthCallsWriter.java b/src/main/java/com/snp/batch/jobs/batch/movement/writer/BerthCallsWriter.java
similarity index 81%
rename from src/main/java/com/snp/batch/jobs/movement/batch/writer/BerthCallsWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/writer/BerthCallsWriter.java
index 9efb091..9152be2 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/writer/BerthCallsWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/writer/BerthCallsWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.writer;
+package com.snp.batch.jobs.batch.movement.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.movement.batch.repository.BerthCallsRepository;
-import com.snp.batch.jobs.movement.batch.entity.BerthCallsEntity;
+import com.snp.batch.jobs.batch.movement.repository.BerthCallsRepository;
+import com.snp.batch.jobs.batch.movement.entity.BerthCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/writer/CurrentlyAtWriter.java b/src/main/java/com/snp/batch/jobs/batch/movement/writer/CurrentlyAtWriter.java
similarity index 81%
rename from src/main/java/com/snp/batch/jobs/movement/batch/writer/CurrentlyAtWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/writer/CurrentlyAtWriter.java
index fbd95fe..7a0b179 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/writer/CurrentlyAtWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/writer/CurrentlyAtWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.writer;
+package com.snp.batch.jobs.batch.movement.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.movement.batch.repository.CurrentlyAtRepository;
-import com.snp.batch.jobs.movement.batch.entity.CurrentlyAtEntity;
+import com.snp.batch.jobs.batch.movement.repository.CurrentlyAtRepository;
+import com.snp.batch.jobs.batch.movement.entity.CurrentlyAtEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/writer/DestinationWriter.java b/src/main/java/com/snp/batch/jobs/batch/movement/writer/DestinationWriter.java
similarity index 81%
rename from src/main/java/com/snp/batch/jobs/movement/batch/writer/DestinationWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/writer/DestinationWriter.java
index a7bf3b5..fa00c12 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/writer/DestinationWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/writer/DestinationWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.writer;
+package com.snp.batch.jobs.batch.movement.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.movement.batch.repository.DestinationRepository;
-import com.snp.batch.jobs.movement.batch.entity.DestinationEntity;
+import com.snp.batch.jobs.batch.movement.repository.DestinationRepository;
+import com.snp.batch.jobs.batch.movement.entity.DestinationEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/writer/PortCallsWriter.java b/src/main/java/com/snp/batch/jobs/batch/movement/writer/PortCallsWriter.java
similarity index 81%
rename from src/main/java/com/snp/batch/jobs/movement/batch/writer/PortCallsWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/writer/PortCallsWriter.java
index 8ec07cf..78d0b8b 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/writer/PortCallsWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/writer/PortCallsWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.writer;
+package com.snp.batch.jobs.batch.movement.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.movement.batch.entity.PortCallsEntity;
-import com.snp.batch.jobs.movement.batch.repository.PortCallsRepository;
+import com.snp.batch.jobs.batch.movement.entity.PortCallsEntity;
+import com.snp.batch.jobs.batch.movement.repository.PortCallsRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/writer/StsOperationWriter.java b/src/main/java/com/snp/batch/jobs/batch/movement/writer/StsOperationWriter.java
similarity index 82%
rename from src/main/java/com/snp/batch/jobs/movement/batch/writer/StsOperationWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/writer/StsOperationWriter.java
index 3decdc1..2c6a8f6 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/writer/StsOperationWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/writer/StsOperationWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.writer;
+package com.snp.batch.jobs.batch.movement.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.movement.batch.repository.StsOperationRepository;
-import com.snp.batch.jobs.movement.batch.entity.StsOperationEntity;
+import com.snp.batch.jobs.batch.movement.repository.StsOperationRepository;
+import com.snp.batch.jobs.batch.movement.entity.StsOperationEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/writer/TerminalCallsWriter.java b/src/main/java/com/snp/batch/jobs/batch/movement/writer/TerminalCallsWriter.java
similarity index 82%
rename from src/main/java/com/snp/batch/jobs/movement/batch/writer/TerminalCallsWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/writer/TerminalCallsWriter.java
index 70c779b..4b8d62f 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/writer/TerminalCallsWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/writer/TerminalCallsWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.writer;
+package com.snp.batch.jobs.batch.movement.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.movement.batch.repository.TerminalCallsRepository;
-import com.snp.batch.jobs.movement.batch.entity.TerminalCallsEntity;
+import com.snp.batch.jobs.batch.movement.repository.TerminalCallsRepository;
+import com.snp.batch.jobs.batch.movement.entity.TerminalCallsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/writer/TransitsWriter.java b/src/main/java/com/snp/batch/jobs/batch/movement/writer/TransitsWriter.java
similarity index 81%
rename from src/main/java/com/snp/batch/jobs/movement/batch/writer/TransitsWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/movement/writer/TransitsWriter.java
index bcf3f49..96b6910 100644
--- a/src/main/java/com/snp/batch/jobs/movement/batch/writer/TransitsWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/movement/writer/TransitsWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.movement.batch.writer;
+package com.snp.batch.jobs.batch.movement.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.movement.batch.repository.TransitsRepository;
-import com.snp.batch.jobs.movement.batch.entity.TransitsEntity;
+import com.snp.batch.jobs.batch.movement.repository.TransitsRepository;
+import com.snp.batch.jobs.batch.movement.entity.TransitsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/config/PscInspectionJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/config/PscInspectionJobConfig.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/config/PscInspectionJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/config/PscInspectionJobConfig.java
index 83ea48f..ebc0e8b 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/config/PscInspectionJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/config/PscInspectionJobConfig.java
@@ -1,14 +1,14 @@
-package com.snp.batch.jobs.pscInspection.batch.config;
+package com.snp.batch.jobs.batch.pscInspection.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.facility.batch.processor.PortDataProcessor;
-import com.snp.batch.jobs.pscInspection.batch.dto.PscInspectionDto;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscInspectionEntity;
-import com.snp.batch.jobs.pscInspection.batch.processor.PscInspectionProcessor;
-import com.snp.batch.jobs.pscInspection.batch.reader.PscApiReader;
-import com.snp.batch.jobs.pscInspection.batch.writer.PscInspectionWriter;
+import com.snp.batch.jobs.batch.facility.processor.PortDataProcessor;
+import com.snp.batch.jobs.batch.pscInspection.dto.PscInspectionDto;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscInspectionEntity;
+import com.snp.batch.jobs.batch.pscInspection.processor.PscInspectionProcessor;
+import com.snp.batch.jobs.batch.pscInspection.reader.PscApiReader;
+import com.snp.batch.jobs.batch.pscInspection.writer.PscInspectionWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscAllCertificateDto.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscAllCertificateDto.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscAllCertificateDto.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscAllCertificateDto.java
index 42540d6..1907919 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscAllCertificateDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscAllCertificateDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.pscInspection.batch.dto;
+package com.snp.batch.jobs.batch.pscInspection.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscApiResponseDto.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscApiResponseDto.java
similarity index 87%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscApiResponseDto.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscApiResponseDto.java
index 1d3af2a..5efb26d 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscApiResponseDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscApiResponseDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.pscInspection.batch.dto;
+package com.snp.batch.jobs.batch.pscInspection.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscApsStatusDto.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscApsStatusDto.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscApsStatusDto.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscApsStatusDto.java
index 8e7f20f..357b497 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscApsStatusDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscApsStatusDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.pscInspection.batch.dto;
+package com.snp.batch.jobs.batch.pscInspection.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscDataSetVersionDto.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscDataSetVersionDto.java
similarity index 78%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscDataSetVersionDto.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscDataSetVersionDto.java
index 41fe574..5742f9f 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscDataSetVersionDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscDataSetVersionDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.pscInspection.batch.dto;
+package com.snp.batch.jobs.batch.pscInspection.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscDefectDto.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscDefectDto.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscDefectDto.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscDefectDto.java
index 3557833..7069b95 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscDefectDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscDefectDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.pscInspection.batch.dto;
+package com.snp.batch.jobs.batch.pscInspection.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscInspectionDto.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscInspectionDto.java
similarity index 98%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscInspectionDto.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscInspectionDto.java
index 066a10e..2e810cd 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/dto/PscInspectionDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/dto/PscInspectionDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.pscInspection.batch.dto;
+package com.snp.batch.jobs.batch.pscInspection.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/entity/PscAllCertificateEntity.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/entity/PscAllCertificateEntity.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/entity/PscAllCertificateEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/entity/PscAllCertificateEntity.java
index 7f7cd96..c6c8a6b 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/entity/PscAllCertificateEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/entity/PscAllCertificateEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.pscInspection.batch.entity;
+package com.snp.batch.jobs.batch.pscInspection.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/entity/PscDefectEntity.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/entity/PscDefectEntity.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/entity/PscDefectEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/entity/PscDefectEntity.java
index 2eb74ba..7054b84 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/entity/PscDefectEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/entity/PscDefectEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.pscInspection.batch.entity;
+package com.snp.batch.jobs.batch.pscInspection.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/entity/PscInspectionEntity.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/entity/PscInspectionEntity.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/entity/PscInspectionEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/entity/PscInspectionEntity.java
index bf54ad8..abaf8d3 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/entity/PscInspectionEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/entity/PscInspectionEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.pscInspection.batch.entity;
+package com.snp.batch.jobs.batch.pscInspection.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/processor/PscInspectionProcessor.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/processor/PscInspectionProcessor.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/processor/PscInspectionProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/processor/PscInspectionProcessor.java
index f49f7c1..ac0c5b6 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/processor/PscInspectionProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/processor/PscInspectionProcessor.java
@@ -1,13 +1,13 @@
-package com.snp.batch.jobs.pscInspection.batch.processor;
+package com.snp.batch.jobs.batch.pscInspection.processor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.pscInspection.batch.dto.PscAllCertificateDto;
-import com.snp.batch.jobs.pscInspection.batch.dto.PscDefectDto;
-import com.snp.batch.jobs.pscInspection.batch.dto.PscInspectionDto;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscAllCertificateEntity;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscDefectEntity;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscInspectionEntity;
+import com.snp.batch.jobs.batch.pscInspection.dto.PscAllCertificateDto;
+import com.snp.batch.jobs.batch.pscInspection.dto.PscDefectDto;
+import com.snp.batch.jobs.batch.pscInspection.dto.PscInspectionDto;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscAllCertificateEntity;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscDefectEntity;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscInspectionEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/reader/PscApiReader.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/reader/PscApiReader.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/reader/PscApiReader.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/reader/PscApiReader.java
index 6d00c24..91a16d0 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/reader/PscApiReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/reader/PscApiReader.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.pscInspection.batch.reader;
+package com.snp.batch.jobs.batch.pscInspection.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.pscInspection.batch.dto.PscApiResponseDto;
-import com.snp.batch.jobs.pscInspection.batch.dto.PscInspectionDto;
+import com.snp.batch.jobs.batch.pscInspection.dto.PscApiResponseDto;
+import com.snp.batch.jobs.batch.pscInspection.dto.PscInspectionDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscAllCertificateRepository.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscAllCertificateRepository.java
similarity index 56%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscAllCertificateRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscAllCertificateRepository.java
index 5d4586a..415f17e 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscAllCertificateRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscAllCertificateRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.pscInspection.batch.repository;
+package com.snp.batch.jobs.batch.pscInspection.repository;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscAllCertificateEntity;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscAllCertificateEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscAllCertificateRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscAllCertificateRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscAllCertificateRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscAllCertificateRepositoryImpl.java
index 9fb897f..780847e 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscAllCertificateRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscAllCertificateRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.pscInspection.batch.repository;
+package com.snp.batch.jobs.batch.pscInspection.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscAllCertificateEntity;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscAllCertificateEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscDefectRepository.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscDefectRepository.java
new file mode 100644
index 0000000..c97eaeb
--- /dev/null
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscDefectRepository.java
@@ -0,0 +1,10 @@
+package com.snp.batch.jobs.batch.pscInspection.repository;
+
+import com.snp.batch.jobs.batch.pscInspection.entity.PscDefectEntity;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscInspectionEntity;
+
+import java.util.List;
+
+public interface PscDefectRepository {
+ void saveDefects(List defects);
+}
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscDefectRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscDefectRepositoryImpl.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscDefectRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscDefectRepositoryImpl.java
index 59daa26..7664742 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscDefectRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscDefectRepositoryImpl.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.pscInspection.batch.repository;
+package com.snp.batch.jobs.batch.pscInspection.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscDefectEntity;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscInspectionEntity;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscDefectEntity;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscInspectionEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscInspectionRepository.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscInspectionRepository.java
similarity index 52%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscInspectionRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscInspectionRepository.java
index 201f6c7..16dc7af 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscInspectionRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscInspectionRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.pscInspection.batch.repository;
+package com.snp.batch.jobs.batch.pscInspection.repository;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscInspectionEntity;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscInspectionEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscInspectionRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscInspectionRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscInspectionRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscInspectionRepositoryImpl.java
index 19dd984..b649ae5 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscInspectionRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/repository/PscInspectionRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.pscInspection.batch.repository;
+package com.snp.batch.jobs.batch.pscInspection.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscInspectionEntity;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscInspectionEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/writer/PscInspectionWriter.java b/src/main/java/com/snp/batch/jobs/batch/pscInspection/writer/PscInspectionWriter.java
similarity index 86%
rename from src/main/java/com/snp/batch/jobs/pscInspection/batch/writer/PscInspectionWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/pscInspection/writer/PscInspectionWriter.java
index 6e2d5cb..2b442d7 100644
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/writer/PscInspectionWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/pscInspection/writer/PscInspectionWriter.java
@@ -1,10 +1,10 @@
-package com.snp.batch.jobs.pscInspection.batch.writer;
+package com.snp.batch.jobs.batch.pscInspection.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscInspectionEntity;
-import com.snp.batch.jobs.pscInspection.batch.repository.PscAllCertificateRepository;
-import com.snp.batch.jobs.pscInspection.batch.repository.PscDefectRepository;
-import com.snp.batch.jobs.pscInspection.batch.repository.PscInspectionRepository;
+import com.snp.batch.jobs.batch.pscInspection.entity.PscInspectionEntity;
+import com.snp.batch.jobs.batch.pscInspection.repository.PscAllCertificateRepository;
+import com.snp.batch.jobs.batch.pscInspection.repository.PscDefectRepository;
+import com.snp.batch.jobs.batch.pscInspection.repository.PscInspectionRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/config/RiskDetailImoFetchTasklet.java b/src/main/java/com/snp/batch/jobs/batch/risk/config/RiskDetailImoFetchTasklet.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/risk/batch/config/RiskDetailImoFetchTasklet.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/config/RiskDetailImoFetchTasklet.java
index a81763c..94ee1eb 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/config/RiskDetailImoFetchTasklet.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/config/RiskDetailImoFetchTasklet.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.risk.batch.config;
+package com.snp.batch.jobs.batch.risk.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.JobExecution;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/config/RiskDetailImportJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/risk/config/RiskDetailImportJobConfig.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/risk/batch/config/RiskDetailImportJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/config/RiskDetailImportJobConfig.java
index ad2e7f7..44768a5 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/config/RiskDetailImportJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/config/RiskDetailImportJobConfig.java
@@ -1,13 +1,13 @@
-package com.snp.batch.jobs.risk.batch.config;
+package com.snp.batch.jobs.batch.risk.config;
import com.snp.batch.common.batch.config.BasePartitionedJobConfig;
import com.snp.batch.common.batch.partition.StringListPartitioner;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.risk.batch.dto.RiskDto;
-import com.snp.batch.jobs.risk.batch.entity.RiskEntity;
-import com.snp.batch.jobs.risk.batch.processor.RiskDataProcessor;
-import com.snp.batch.jobs.risk.batch.reader.RiskDetailDataReader;
-import com.snp.batch.jobs.risk.batch.writer.RiskDetailDataWriter;
+import com.snp.batch.jobs.batch.risk.dto.RiskDto;
+import com.snp.batch.jobs.batch.risk.entity.RiskEntity;
+import com.snp.batch.jobs.batch.risk.processor.RiskDataProcessor;
+import com.snp.batch.jobs.batch.risk.reader.RiskDetailDataReader;
+import com.snp.batch.jobs.batch.risk.writer.RiskDetailDataWriter;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/config/RiskImportRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/risk/config/RiskImportRangeJobConfig.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/risk/batch/config/RiskImportRangeJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/config/RiskImportRangeJobConfig.java
index f68cc89..34de74e 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/config/RiskImportRangeJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/config/RiskImportRangeJobConfig.java
@@ -1,12 +1,12 @@
-package com.snp.batch.jobs.risk.batch.config;
+package com.snp.batch.jobs.batch.risk.config;
import com.snp.batch.common.batch.config.BaseMultiStepJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
-import com.snp.batch.jobs.risk.batch.dto.RiskDto;
-import com.snp.batch.jobs.risk.batch.entity.RiskEntity;
-import com.snp.batch.jobs.risk.batch.processor.RiskDataProcessor;
-import com.snp.batch.jobs.risk.batch.reader.RiskDataRangeReader;
-import com.snp.batch.jobs.risk.batch.writer.RiskDetailDataWriter;
+import com.snp.batch.jobs.batch.risk.dto.RiskDto;
+import com.snp.batch.jobs.batch.risk.entity.RiskEntity;
+import com.snp.batch.jobs.batch.risk.processor.RiskDataProcessor;
+import com.snp.batch.jobs.batch.risk.reader.RiskDataRangeReader;
+import com.snp.batch.jobs.batch.risk.writer.RiskDetailDataWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/dto/RiskDto.java b/src/main/java/com/snp/batch/jobs/batch/risk/dto/RiskDto.java
similarity index 99%
rename from src/main/java/com/snp/batch/jobs/risk/batch/dto/RiskDto.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/dto/RiskDto.java
index 6797e1c..2580eed 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/dto/RiskDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/dto/RiskDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.risk.batch.dto;
+package com.snp.batch.jobs.batch.risk.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/dto/RiskResponse.java b/src/main/java/com/snp/batch/jobs/batch/risk/dto/RiskResponse.java
similarity index 85%
rename from src/main/java/com/snp/batch/jobs/risk/batch/dto/RiskResponse.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/dto/RiskResponse.java
index 1ab23e9..697b8b4 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/dto/RiskResponse.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/dto/RiskResponse.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.risk.batch.dto;
+package com.snp.batch.jobs.batch.risk.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/entity/RiskEntity.java b/src/main/java/com/snp/batch/jobs/batch/risk/entity/RiskEntity.java
similarity index 98%
rename from src/main/java/com/snp/batch/jobs/risk/batch/entity/RiskEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/entity/RiskEntity.java
index e5ccc1c..4ca4822 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/entity/RiskEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/entity/RiskEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.risk.batch.entity;
+package com.snp.batch.jobs.batch.risk.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/processor/RiskDataProcessor.java b/src/main/java/com/snp/batch/jobs/batch/risk/processor/RiskDataProcessor.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/risk/batch/processor/RiskDataProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/processor/RiskDataProcessor.java
index ca2a293..4f5415d 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/processor/RiskDataProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/processor/RiskDataProcessor.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.risk.batch.processor;
+package com.snp.batch.jobs.batch.risk.processor;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.risk.batch.dto.RiskDto;
-import com.snp.batch.jobs.risk.batch.entity.RiskEntity;
+import com.snp.batch.jobs.batch.risk.dto.RiskDto;
+import com.snp.batch.jobs.batch.risk.entity.RiskEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/reader/RiskDataRangeReader.java b/src/main/java/com/snp/batch/jobs/batch/risk/reader/RiskDataRangeReader.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/risk/batch/reader/RiskDataRangeReader.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/reader/RiskDataRangeReader.java
index cae2ee1..ed75282 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/reader/RiskDataRangeReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/reader/RiskDataRangeReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.risk.batch.reader;
+package com.snp.batch.jobs.batch.risk.reader;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.risk.batch.dto.RiskDto;
+import com.snp.batch.jobs.batch.risk.dto.RiskDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/reader/RiskDetailDataReader.java b/src/main/java/com/snp/batch/jobs/batch/risk/reader/RiskDetailDataReader.java
similarity index 98%
rename from src/main/java/com/snp/batch/jobs/risk/batch/reader/RiskDetailDataReader.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/reader/RiskDetailDataReader.java
index 2e8e19a..31efaae 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/reader/RiskDetailDataReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/reader/RiskDetailDataReader.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.risk.batch.reader;
+package com.snp.batch.jobs.batch.risk.reader;
import com.snp.batch.global.model.BatchApiLog;
-import com.snp.batch.jobs.risk.batch.dto.RiskDto;
+import com.snp.batch.jobs.batch.risk.dto.RiskDto;
import com.snp.batch.service.BatchApiLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.item.ItemReader;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/repository/RiskRepository.java b/src/main/java/com/snp/batch/jobs/batch/risk/repository/RiskRepository.java
similarity index 66%
rename from src/main/java/com/snp/batch/jobs/risk/batch/repository/RiskRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/repository/RiskRepository.java
index 317e198..2cda84a 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/repository/RiskRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/repository/RiskRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.risk.batch.repository;
+package com.snp.batch.jobs.batch.risk.repository;
-import com.snp.batch.jobs.risk.batch.entity.RiskEntity;
+import com.snp.batch.jobs.batch.risk.entity.RiskEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/repository/RiskRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/risk/repository/RiskRepositoryImpl.java
similarity index 99%
rename from src/main/java/com/snp/batch/jobs/risk/batch/repository/RiskRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/repository/RiskRepositoryImpl.java
index 472da66..72fc1fd 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/repository/RiskRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/repository/RiskRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.risk.batch.repository;
+package com.snp.batch.jobs.batch.risk.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.risk.batch.entity.RiskEntity;
+import com.snp.batch.jobs.batch.risk.entity.RiskEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/writer/RiskDataWriter.java b/src/main/java/com/snp/batch/jobs/batch/risk/writer/RiskDataWriter.java
similarity index 78%
rename from src/main/java/com/snp/batch/jobs/risk/batch/writer/RiskDataWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/writer/RiskDataWriter.java
index 658e468..64b01b5 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/writer/RiskDataWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/writer/RiskDataWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.risk.batch.writer;
+package com.snp.batch.jobs.batch.risk.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.risk.batch.entity.RiskEntity;
-import com.snp.batch.jobs.risk.batch.repository.RiskRepository;
+import com.snp.batch.jobs.batch.risk.entity.RiskEntity;
+import com.snp.batch.jobs.batch.risk.repository.RiskRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/writer/RiskDetailDataWriter.java b/src/main/java/com/snp/batch/jobs/batch/risk/writer/RiskDetailDataWriter.java
similarity index 78%
rename from src/main/java/com/snp/batch/jobs/risk/batch/writer/RiskDetailDataWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/risk/writer/RiskDetailDataWriter.java
index fba0d13..293873f 100644
--- a/src/main/java/com/snp/batch/jobs/risk/batch/writer/RiskDetailDataWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/risk/writer/RiskDetailDataWriter.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.risk.batch.writer;
+package com.snp.batch.jobs.batch.risk.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.risk.batch.entity.RiskEntity;
-import com.snp.batch.jobs.risk.batch.repository.RiskRepository;
+import com.snp.batch.jobs.batch.risk.entity.RiskEntity;
+import com.snp.batch.jobs.batch.risk.repository.RiskRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailImoFetchTasklet.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/config/ShipDetailImoFetchTasklet.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailImoFetchTasklet.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/config/ShipDetailImoFetchTasklet.java
index 713307d..84f250b 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailImoFetchTasklet.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/config/ShipDetailImoFetchTasklet.java
@@ -1,9 +1,9 @@
-package com.snp.batch.jobs.shipdetail.batch.config;
+package com.snp.batch.jobs.batch.shipdetail.config;
import com.snp.batch.global.model.BatchApiLog;
import com.snp.batch.global.repository.BatchFailedRecordRepository;
-import com.snp.batch.jobs.shipdetail.batch.dto.ShipDto;
-import com.snp.batch.jobs.shipdetail.batch.dto.ShipUpdateApiResponse;
+import com.snp.batch.jobs.batch.shipdetail.dto.ShipDto;
+import com.snp.batch.jobs.batch.shipdetail.dto.ShipUpdateApiResponse;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailPartitioner.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/config/ShipDetailPartitioner.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailPartitioner.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/config/ShipDetailPartitioner.java
index 1cbaa3f..1b1f7bd 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailPartitioner.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/config/ShipDetailPartitioner.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.config;
+package com.snp.batch.jobs.batch.shipdetail.config;
import com.snp.batch.common.batch.partition.StringListPartitioner;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailUpdateJobConfig.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/config/ShipDetailUpdateJobConfig.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailUpdateJobConfig.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/config/ShipDetailUpdateJobConfig.java
index 1b911ba..4e2298a 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailUpdateJobConfig.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/config/ShipDetailUpdateJobConfig.java
@@ -1,14 +1,14 @@
-package com.snp.batch.jobs.shipdetail.batch.config;
+package com.snp.batch.jobs.batch.shipdetail.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.config.BasePartitionedJobConfig;
import com.snp.batch.common.batch.tasklet.LastExecutionUpdateTasklet;
import com.snp.batch.global.repository.BatchFailedRecordRepository;
-import com.snp.batch.jobs.shipdetail.batch.dto.ShipDetailDto;
-import com.snp.batch.jobs.shipdetail.batch.entity.ShipDetailEntity;
-import com.snp.batch.jobs.shipdetail.batch.processor.ShipDetailDataProcessor;
-import com.snp.batch.jobs.shipdetail.batch.reader.ShipDetailUpdateDataReader;
-import com.snp.batch.jobs.shipdetail.batch.writer.ShipDetailDataWriter;
+import com.snp.batch.jobs.batch.shipdetail.dto.ShipDetailDto;
+import com.snp.batch.jobs.batch.shipdetail.entity.ShipDetailEntity;
+import com.snp.batch.jobs.batch.shipdetail.processor.ShipDetailDataProcessor;
+import com.snp.batch.jobs.batch.shipdetail.reader.ShipDetailUpdateDataReader;
+import com.snp.batch.jobs.batch.shipdetail.writer.ShipDetailDataWriter;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import com.snp.batch.service.BatchFailedRecordService;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/AdditionalInformationDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/AdditionalInformationDto.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/AdditionalInformationDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/AdditionalInformationDto.java
index ffb07d6..aea8f1d 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/AdditionalInformationDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/AdditionalInformationDto.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.AdditionalInformationEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.AdditionalInformationEntity;
import lombok.*;
@Getter
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/BareBoatCharterHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/BareBoatCharterHistoryDto.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/BareBoatCharterHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/BareBoatCharterHistoryDto.java
index 10c2d1f..08031ea 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/BareBoatCharterHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/BareBoatCharterHistoryDto.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.BareBoatCharterHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.BareBoatCharterHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CallSignAndMmsiHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CallSignAndMmsiHistoryDto.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CallSignAndMmsiHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CallSignAndMmsiHistoryDto.java
index 861dc46..2493f3d 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CallSignAndMmsiHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CallSignAndMmsiHistoryDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.CallSignAndMmsiHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.CallSignAndMmsiHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ClassHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ClassHistoryDto.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ClassHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ClassHistoryDto.java
index 73630e6..0b806c4 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ClassHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ClassHistoryDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.ClassHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.ClassHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CompanyDetailDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CompanyDetailDto.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CompanyDetailDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CompanyDetailDto.java
index bfd9402..4d9cef3 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CompanyDetailDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CompanyDetailDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.CompanyDetailEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.CompanyDetailEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CompanyVesselRelationshipDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CompanyVesselRelationshipDto.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CompanyVesselRelationshipDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CompanyVesselRelationshipDto.java
index 3dace6e..cfd5f10 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CompanyVesselRelationshipDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CompanyVesselRelationshipDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.CompanyVesselRelationshipEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.CompanyVesselRelationshipEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CrewListDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CrewListDto.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CrewListDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CrewListDto.java
index 6a7ec75..ca185f1 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/CrewListDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/CrewListDto.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.CrewListEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.CrewListEntity;
import lombok.*;
@Data
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/DarkActivityConfirmedDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/DarkActivityConfirmedDto.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/DarkActivityConfirmedDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/DarkActivityConfirmedDto.java
index b868ccc..888047c 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/DarkActivityConfirmedDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/DarkActivityConfirmedDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.DarkActivityConfirmedEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.DarkActivityConfirmedEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/FlagHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/FlagHistoryDto.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/FlagHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/FlagHistoryDto.java
index e27f484..39fac3d 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/FlagHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/FlagHistoryDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.FlagHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.FlagHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/GroupBeneficialOwnerHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/GroupBeneficialOwnerHistoryDto.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/GroupBeneficialOwnerHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/GroupBeneficialOwnerHistoryDto.java
index 34a04fa..4f7e101 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/GroupBeneficialOwnerHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/GroupBeneficialOwnerHistoryDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.GroupBeneficialOwnerHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.GroupBeneficialOwnerHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/IceClassDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/IceClassDto.java
similarity index 89%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/IceClassDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/IceClassDto.java
index d639b52..55ec590 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/IceClassDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/IceClassDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.IceClassEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.IceClassEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/NameHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/NameHistoryDto.java
similarity index 90%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/NameHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/NameHistoryDto.java
index 1ee30f7..da1d2d0 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/NameHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/NameHistoryDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.NameHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.NameHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/OperatorHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/OperatorHistoryDto.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/OperatorHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/OperatorHistoryDto.java
index a3db024..106250f 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/OperatorHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/OperatorHistoryDto.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.OperatorHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.OperatorHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/OwnerHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/OwnerHistoryDto.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/OwnerHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/OwnerHistoryDto.java
index ceacd38..42d8f69 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/OwnerHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/OwnerHistoryDto.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.OwnerHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.OwnerHistoryEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/PandIHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/PandIHistoryDto.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/PandIHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/PandIHistoryDto.java
index d6e1567..9ea963b 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/PandIHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/PandIHistoryDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.PandIHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.PandIHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SafetyManagementCertificateHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SafetyManagementCertificateHistoryDto.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SafetyManagementCertificateHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SafetyManagementCertificateHistoryDto.java
index c993285..16df2cf 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SafetyManagementCertificateHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SafetyManagementCertificateHistoryDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.SafetyManagementCertificateHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.SafetyManagementCertificateHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailApiResponse.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailApiResponse.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailApiResponse.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailApiResponse.java
index dda21df..3e0a019 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailApiResponse.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailApiResponse.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailComparisonData.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailComparisonData.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailComparisonData.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailComparisonData.java
index 90c2ecb..1692036 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailComparisonData.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailComparisonData.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import lombok.Builder;
import lombok.Getter;
import java.util.Map;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailDto.java
similarity index 99%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailDto.java
index 3cee449..e6ed1a8 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailUpdate.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailUpdate.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailUpdate.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailUpdate.java
index 2c3f87e..a2d03f0 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDetailUpdate.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDetailUpdate.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
-import com.snp.batch.jobs.shipdetail.batch.entity.*;
+import com.snp.batch.jobs.batch.shipdetail.entity.*;
import lombok.Builder;
import lombok.Getter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDto.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDto.java
index ba849b2..a2fde4e 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipManagerHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipManagerHistoryDto.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipManagerHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipManagerHistoryDto.java
index 4274828..7b93a7f 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipManagerHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipManagerHistoryDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.ShipManagerHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.ShipManagerHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipResultDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipResultDto.java
similarity index 90%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipResultDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipResultDto.java
index 22d5faa..556e4ab 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipResultDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipResultDto.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipUpdateApiResponse.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipUpdateApiResponse.java
similarity index 90%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipUpdateApiResponse.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipUpdateApiResponse.java
index b4d70d3..03416b6 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ShipUpdateApiResponse.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ShipUpdateApiResponse.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SisterShipLinksDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SisterShipLinksDto.java
similarity index 89%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SisterShipLinksDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SisterShipLinksDto.java
index d18dcab..6c1931b 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SisterShipLinksDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SisterShipLinksDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.SisterShipLinksEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.SisterShipLinksEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SpecialFeatureDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SpecialFeatureDto.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SpecialFeatureDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SpecialFeatureDto.java
index 571a7d0..6dd33fc 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SpecialFeatureDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SpecialFeatureDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.SpecialFeatureEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.SpecialFeatureEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/StatusHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/StatusHistoryDto.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/StatusHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/StatusHistoryDto.java
index f36c11c..d3a1c86 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/StatusHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/StatusHistoryDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.StatusHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.StatusHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/StowageCommodityDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/StowageCommodityDto.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/StowageCommodityDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/StowageCommodityDto.java
index 2b7bf42..585f41b 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/StowageCommodityDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/StowageCommodityDto.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.StowageCommodityEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.StowageCommodityEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SurveyDatesHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SurveyDatesHistoryDto.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SurveyDatesHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SurveyDatesHistoryDto.java
index 41937dc..aa2c5d2 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SurveyDatesHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SurveyDatesHistoryDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.SurveyDatesHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.SurveyDatesHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SurveyDatesHistoryUniqueDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SurveyDatesHistoryUniqueDto.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SurveyDatesHistoryUniqueDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SurveyDatesHistoryUniqueDto.java
index d5ec0e5..afafda4 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/SurveyDatesHistoryUniqueDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/SurveyDatesHistoryUniqueDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.SurveyDatesHistoryUniqueEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.SurveyDatesHistoryUniqueEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/TechnicalManagerHistoryDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/TechnicalManagerHistoryDto.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/TechnicalManagerHistoryDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/TechnicalManagerHistoryDto.java
index 250e5a8..590ea5b 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/TechnicalManagerHistoryDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/TechnicalManagerHistoryDto.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.TechnicalManagerHistoryEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.TechnicalManagerHistoryEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ThrustersDto.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ThrustersDto.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ThrustersDto.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ThrustersDto.java
index b6abce5..3ce623e 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/dto/ThrustersDto.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/dto/ThrustersDto.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.dto;
+package com.snp.batch.jobs.batch.shipdetail.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.snp.batch.jobs.shipdetail.batch.entity.ThrustersEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.ThrustersEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/AdditionalInformationEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/AdditionalInformationEntity.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/AdditionalInformationEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/AdditionalInformationEntity.java
index 06107b2..de9a8ab 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/AdditionalInformationEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/AdditionalInformationEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/BareBoatCharterHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/BareBoatCharterHistoryEntity.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/BareBoatCharterHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/BareBoatCharterHistoryEntity.java
index 0bea631..26f934d 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/BareBoatCharterHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/BareBoatCharterHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CallSignAndMmsiHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CallSignAndMmsiHistoryEntity.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CallSignAndMmsiHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CallSignAndMmsiHistoryEntity.java
index a8527d7..5ee60de 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CallSignAndMmsiHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CallSignAndMmsiHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ClassHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ClassHistoryEntity.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ClassHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ClassHistoryEntity.java
index ca8dfcf..24c5c87 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ClassHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ClassHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CompanyDetailEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CompanyDetailEntity.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CompanyDetailEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CompanyDetailEntity.java
index 98ecd3a..08c4206 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CompanyDetailEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CompanyDetailEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CompanyVesselRelationshipEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CompanyVesselRelationshipEntity.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CompanyVesselRelationshipEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CompanyVesselRelationshipEntity.java
index e799e31..9ffc9d8 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CompanyVesselRelationshipEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CompanyVesselRelationshipEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CrewListEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CrewListEntity.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CrewListEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CrewListEntity.java
index 86841af..e77cbe0 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/CrewListEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/CrewListEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/DarkActivityConfirmedEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/DarkActivityConfirmedEntity.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/DarkActivityConfirmedEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/DarkActivityConfirmedEntity.java
index f121368..b9ba5fd 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/DarkActivityConfirmedEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/DarkActivityConfirmedEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/FlagHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/FlagHistoryEntity.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/FlagHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/FlagHistoryEntity.java
index 4dc1b2e..6646582 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/FlagHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/FlagHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/GroupBeneficialOwnerHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/GroupBeneficialOwnerHistoryEntity.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/GroupBeneficialOwnerHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/GroupBeneficialOwnerHistoryEntity.java
index df62d89..b474dac 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/GroupBeneficialOwnerHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/GroupBeneficialOwnerHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/IceClassEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/IceClassEntity.java
similarity index 90%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/IceClassEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/IceClassEntity.java
index a019a9a..54b9ff8 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/IceClassEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/IceClassEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/NameHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/NameHistoryEntity.java
similarity index 90%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/NameHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/NameHistoryEntity.java
index 2b974c6..000a664 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/NameHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/NameHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/OperatorHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/OperatorHistoryEntity.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/OperatorHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/OperatorHistoryEntity.java
index c5ddf83..826d738 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/OperatorHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/OperatorHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/OwnerHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/OwnerHistoryEntity.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/OwnerHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/OwnerHistoryEntity.java
index ccd1ff9..80a06e3 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/OwnerHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/OwnerHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/PandIHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/PandIHistoryEntity.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/PandIHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/PandIHistoryEntity.java
index dfcc3d1..9c1af1c 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/PandIHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/PandIHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SafetyManagementCertificateHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SafetyManagementCertificateHistoryEntity.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SafetyManagementCertificateHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SafetyManagementCertificateHistoryEntity.java
index 8ec438f..790127d 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SafetyManagementCertificateHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SafetyManagementCertificateHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ShipDetailEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ShipDetailEntity.java
similarity index 99%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ShipDetailEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ShipDetailEntity.java
index b0804db..617da18 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ShipDetailEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ShipDetailEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ShipHashEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ShipHashEntity.java
similarity index 89%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ShipHashEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ShipHashEntity.java
index 3308325..5043e35 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ShipHashEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ShipHashEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ShipManagerHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ShipManagerHistoryEntity.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ShipManagerHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ShipManagerHistoryEntity.java
index 4fb5cca..2757146 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ShipManagerHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ShipManagerHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SisterShipLinksEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SisterShipLinksEntity.java
similarity index 89%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SisterShipLinksEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SisterShipLinksEntity.java
index dd7a084..04a05e7 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SisterShipLinksEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SisterShipLinksEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SpecialFeatureEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SpecialFeatureEntity.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SpecialFeatureEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SpecialFeatureEntity.java
index da57585..d7badea 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SpecialFeatureEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SpecialFeatureEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/StatusHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/StatusHistoryEntity.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/StatusHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/StatusHistoryEntity.java
index 48deefb..56bf51b 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/StatusHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/StatusHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/StowageCommodityEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/StowageCommodityEntity.java
similarity index 94%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/StowageCommodityEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/StowageCommodityEntity.java
index 3934d95..bb44740 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/StowageCommodityEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/StowageCommodityEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SurveyDatesHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SurveyDatesHistoryEntity.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SurveyDatesHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SurveyDatesHistoryEntity.java
index 254d128..3a067d4 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SurveyDatesHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SurveyDatesHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SurveyDatesHistoryUniqueEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SurveyDatesHistoryUniqueEntity.java
similarity index 91%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SurveyDatesHistoryUniqueEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SurveyDatesHistoryUniqueEntity.java
index 47f1ebc..b85bd9d 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/SurveyDatesHistoryUniqueEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/SurveyDatesHistoryUniqueEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/TechnicalManagerHistoryEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/TechnicalManagerHistoryEntity.java
similarity index 92%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/TechnicalManagerHistoryEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/TechnicalManagerHistoryEntity.java
index 996c761..9c9df56 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/TechnicalManagerHistoryEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/TechnicalManagerHistoryEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ThrustersEntity.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ThrustersEntity.java
similarity index 93%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ThrustersEntity.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ThrustersEntity.java
index 9067d73..4efc24e 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/entity/ThrustersEntity.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/entity/ThrustersEntity.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.entity;
+package com.snp.batch.jobs.batch.shipdetail.entity;
import com.snp.batch.common.batch.entity.BaseEntity;
import lombok.AllArgsConstructor;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/processor/ShipDetailDataProcessor.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/processor/ShipDetailDataProcessor.java
similarity index 99%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/processor/ShipDetailDataProcessor.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/processor/ShipDetailDataProcessor.java
index 7186342..600a64f 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/processor/ShipDetailDataProcessor.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/processor/ShipDetailDataProcessor.java
@@ -1,8 +1,8 @@
-package com.snp.batch.jobs.shipdetail.batch.processor;
+package com.snp.batch.jobs.batch.shipdetail.processor;
import com.snp.batch.common.batch.processor.BaseProcessor;
-import com.snp.batch.jobs.shipdetail.batch.dto.*;
-import com.snp.batch.jobs.shipdetail.batch.entity.*;
+import com.snp.batch.jobs.batch.shipdetail.dto.*;
+import com.snp.batch.jobs.batch.shipdetail.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/reader/ShipDetailUpdateDataReader.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/reader/ShipDetailUpdateDataReader.java
similarity index 98%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/reader/ShipDetailUpdateDataReader.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/reader/ShipDetailUpdateDataReader.java
index 1ccd51d..a4716e4 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/reader/ShipDetailUpdateDataReader.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/reader/ShipDetailUpdateDataReader.java
@@ -1,10 +1,10 @@
-package com.snp.batch.jobs.shipdetail.batch.reader;
+package com.snp.batch.jobs.batch.shipdetail.reader;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snp.batch.common.batch.reader.BaseApiReader;
-import com.snp.batch.jobs.shipdetail.batch.dto.ShipDetailApiResponse;
-import com.snp.batch.jobs.shipdetail.batch.dto.ShipDetailDto;
-import com.snp.batch.jobs.shipdetail.batch.dto.ShipResultDto;
+import com.snp.batch.jobs.batch.shipdetail.dto.ShipDetailApiResponse;
+import com.snp.batch.jobs.batch.shipdetail.dto.ShipDetailDto;
+import com.snp.batch.jobs.batch.shipdetail.dto.ShipResultDto;
import com.snp.batch.service.BatchApiLogService;
import com.snp.batch.service.BatchDateService;
import com.snp.batch.service.BatchFailedRecordService;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipDetailRepository.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipDetailRepository.java
similarity index 95%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipDetailRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipDetailRepository.java
index 11e1ce6..ec03a52 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipDetailRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipDetailRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.shipdetail.batch.repository;
+package com.snp.batch.jobs.batch.shipdetail.repository;
-import com.snp.batch.jobs.shipdetail.batch.entity.*;
+import com.snp.batch.jobs.batch.shipdetail.entity.*;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipDetailRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipDetailRepositoryImpl.java
similarity index 99%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipDetailRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipDetailRepositoryImpl.java
index e70f8fb..359ad6c 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipDetailRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipDetailRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.repository;
+package com.snp.batch.jobs.batch.shipdetail.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.shipdetail.batch.entity.*;
+import com.snp.batch.jobs.batch.shipdetail.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipDetailSql.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipDetailSql.java
similarity index 99%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipDetailSql.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipDetailSql.java
index 89e5bb9..db92f51 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipDetailSql.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipDetailSql.java
@@ -1,4 +1,4 @@
-package com.snp.batch.jobs.shipdetail.batch.repository;
+package com.snp.batch.jobs.batch.shipdetail.repository;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipHashRepository.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipHashRepository.java
similarity index 50%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipHashRepository.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipHashRepository.java
index cf12ff4..cd96098 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipHashRepository.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipHashRepository.java
@@ -1,6 +1,6 @@
-package com.snp.batch.jobs.shipdetail.batch.repository;
+package com.snp.batch.jobs.batch.shipdetail.repository;
-import com.snp.batch.jobs.shipdetail.batch.entity.ShipHashEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.ShipHashEntity;
import java.util.List;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipHashRepositoryImpl.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipHashRepositoryImpl.java
similarity index 97%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipHashRepositoryImpl.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipHashRepositoryImpl.java
index bac872b..10b682f 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/repository/ShipHashRepositoryImpl.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/repository/ShipHashRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.snp.batch.jobs.shipdetail.batch.repository;
+package com.snp.batch.jobs.batch.shipdetail.repository;
import com.snp.batch.common.batch.repository.BaseJdbcRepository;
-import com.snp.batch.jobs.shipdetail.batch.entity.ShipHashEntity;
+import com.snp.batch.jobs.batch.shipdetail.entity.ShipHashEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/writer/ShipDetailDataWriter.java b/src/main/java/com/snp/batch/jobs/batch/shipdetail/writer/ShipDetailDataWriter.java
similarity index 96%
rename from src/main/java/com/snp/batch/jobs/shipdetail/batch/writer/ShipDetailDataWriter.java
rename to src/main/java/com/snp/batch/jobs/batch/shipdetail/writer/ShipDetailDataWriter.java
index dabc3d7..8a7fa22 100644
--- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/writer/ShipDetailDataWriter.java
+++ b/src/main/java/com/snp/batch/jobs/batch/shipdetail/writer/ShipDetailDataWriter.java
@@ -1,10 +1,10 @@
-package com.snp.batch.jobs.shipdetail.batch.writer;
+package com.snp.batch.jobs.batch.shipdetail.writer;
import com.snp.batch.common.batch.writer.BaseWriter;
-import com.snp.batch.jobs.shipdetail.batch.dto.ShipDetailUpdate;
-import com.snp.batch.jobs.shipdetail.batch.entity.*;
-import com.snp.batch.jobs.shipdetail.batch.repository.ShipDetailRepository;
-import com.snp.batch.jobs.shipdetail.batch.repository.ShipHashRepository;
+import com.snp.batch.jobs.batch.shipdetail.dto.ShipDetailUpdate;
+import com.snp.batch.jobs.batch.shipdetail.entity.*;
+import com.snp.batch.jobs.batch.shipdetail.repository.ShipDetailRepository;
+import com.snp.batch.jobs.batch.shipdetail.repository.ShipHashRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
diff --git a/src/main/java/com/snp/batch/jobs/event/batch/repository/EventRepository.java b/src/main/java/com/snp/batch/jobs/event/batch/repository/EventRepository.java
deleted file mode 100644
index da65ba6..0000000
--- a/src/main/java/com/snp/batch/jobs/event/batch/repository/EventRepository.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.snp.batch.jobs.event.batch.repository;
-
-import com.snp.batch.jobs.event.batch.entity.CargoEntity;
-import com.snp.batch.jobs.event.batch.entity.EventDetailEntity;
-import com.snp.batch.jobs.event.batch.entity.HumanCasualtyEntity;
-import com.snp.batch.jobs.event.batch.entity.RelationshipEntity;
-
-import java.util.List;
-
-public interface EventRepository {
- void saveEventAll(List items);
- void saveCargoAll(List items);
- void saveHumanCasualtyAll(List items);
- void saveRelationshipAll(List items);
-}
diff --git a/src/main/java/com/snp/batch/jobs/facility/batch/repository/FacilityRepository.java b/src/main/java/com/snp/batch/jobs/facility/batch/repository/FacilityRepository.java
deleted file mode 100644
index 358b068..0000000
--- a/src/main/java/com/snp/batch/jobs/facility/batch/repository/FacilityRepository.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.snp.batch.jobs.facility.batch.repository;
-
-import com.snp.batch.jobs.facility.batch.entity.PortEntity;
-
-import java.util.List;
-
-public interface FacilityRepository {
- void savePortAll(List items);
-}
diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscDefectRepository.java b/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscDefectRepository.java
deleted file mode 100644
index 35d9029..0000000
--- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/repository/PscDefectRepository.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.snp.batch.jobs.pscInspection.batch.repository;
-
-import com.snp.batch.jobs.pscInspection.batch.entity.PscDefectEntity;
-import com.snp.batch.jobs.pscInspection.batch.entity.PscInspectionEntity;
-
-import java.util.List;
-
-public interface PscDefectRepository {
- void saveDefects(List defects);
-}
diff --git a/src/main/java/com/snp/batch/jobs/risk/web/controller/RiskController.java b/src/main/java/com/snp/batch/jobs/risk/web/controller/RiskController.java
deleted file mode 100644
index 9113622..0000000
--- a/src/main/java/com/snp/batch/jobs/risk/web/controller/RiskController.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.snp.batch.jobs.risk.web.controller;
-
-import com.snp.batch.common.web.ApiResponse;
-import com.snp.batch.jobs.risk.batch.dto.RiskDto;
-import com.snp.batch.jobs.risk.web.service.RiskBypassService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-
-import java.util.List;
-
-/**
- * Risk 상세 조회 bypass API
- * S&P Maritime API에서 Risk 데이터를 실시간 조회하여 그대로 반환
- */
-@Slf4j
-@RestController
-@RequestMapping("/api/risk")
-@RequiredArgsConstructor
-@Tag(name = "Risk", description = "선박 Risk 상세 정보 bypass API")
-public class RiskController {
-
- private final RiskBypassService riskBypassService;
-
- @Operation(
- summary = "IMO 기반 Risk 상세 조회",
- description = "S&P API에 IMO 번호로 Risk 상세 데이터를 요청하고 응답을 그대로 반환합니다."
- )
- @GetMapping("/{imo}")
- public ResponseEntity>> getRiskDetailByImo(
- @Parameter(description = "IMO 번호", example = "9321483")
- @PathVariable String imo
- ) {
- try {
- List riskData = riskBypassService.getRiskDetailByImo(imo);
- return ResponseEntity.ok(ApiResponse.success(riskData));
- } catch (WebClientResponseException e) {
- log.error("S&P Risk API 호출 실패 - IMO: {}, status: {}, body: {}",
- imo, e.getStatusCode(), e.getResponseBodyAsString());
- return ResponseEntity.status(e.getStatusCode())
- .body(ApiResponse.error("S&P API 호출 실패: " + e.getMessage()));
- } catch (Exception e) {
- log.error("Risk 상세 조회 중 오류 - IMO: {}", imo, e);
- return ResponseEntity.internalServerError()
- .body(ApiResponse.error("Risk 조회 실패: " + e.getMessage()));
- }
- }
-}
diff --git a/src/main/java/com/snp/batch/jobs/risk/web/service/RiskBypassService.java b/src/main/java/com/snp/batch/jobs/risk/web/service/RiskBypassService.java
deleted file mode 100644
index 5162dc9..0000000
--- a/src/main/java/com/snp/batch/jobs/risk/web/service/RiskBypassService.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.snp.batch.jobs.risk.web.service;
-
-import com.snp.batch.jobs.risk.batch.dto.RiskDto;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.core.ParameterizedTypeReference;
-import org.springframework.stereotype.Service;
-import org.springframework.web.reactive.function.client.WebClient;
-
-import java.util.List;
-
-/**
- * S&P Risk API bypass 서비스
- * 외부 Maritime API에서 Risk 상세 데이터를 실시간 조회하여 그대로 반환
- */
-@Slf4j
-@Service
-public class RiskBypassService {
-
- private static final String RISK_API_PATH = "/RiskAndCompliance/RisksByImos";
-
- private final WebClient webClient;
-
- public RiskBypassService(
- @Qualifier("maritimeServiceApiWebClient") WebClient webClient
- ) {
- this.webClient = webClient;
- }
-
- /**
- * IMO 번호로 S&P Risk 상세 데이터를 조회합니다.
- *
- * @param imo IMO 번호
- * @return Risk 상세 데이터 목록
- */
- public List getRiskDetailByImo(String imo) {
- log.info("S&P Risk API 호출 - IMO: {}", imo);
-
- List response = webClient.get()
- .uri(uriBuilder -> uriBuilder
- .path(RISK_API_PATH)
- .queryParam("imos", imo)
- .build())
- .retrieve()
- .bodyToMono(new ParameterizedTypeReference>() {})
- .block();
-
- if (response == null || response.isEmpty()) {
- log.warn("S&P Risk API 응답 없음 - IMO: {}", imo);
- return List.of();
- }
-
- log.info("S&P Risk API 응답 완료 - IMO: {}, 건수: {}", imo, response.size());
- return response;
- }
-}
diff --git a/src/main/java/com/snp/batch/service/BypassCodeGenerator.java b/src/main/java/com/snp/batch/service/BypassCodeGenerator.java
new file mode 100644
index 0000000..540896d
--- /dev/null
+++ b/src/main/java/com/snp/batch/service/BypassCodeGenerator.java
@@ -0,0 +1,386 @@
+package com.snp.batch.service;
+
+import com.snp.batch.global.dto.CodeGenerationResult;
+import com.snp.batch.global.model.BypassApiConfig;
+import com.snp.batch.global.model.BypassApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * BYPASS API Java 소스 코드를 자동 생성하는 서비스.
+ * 모든 API는 RAW 모드(JsonNode 패스스루)로 생성됩니다.
+ * 같은 도메인의 N개 설정을 받아 N개의 Service와 1개의 Controller를 생성합니다.
+ */
+@Slf4j
+@Service
+public class BypassCodeGenerator {
+
+ private static final String BASE_PACKAGE = "com.snp.batch.jobs.web";
+
+ /**
+ * 같은 도메인의 BYPASS API 코드를 생성합니다.
+ * 엔드포인트별 Service를 각각 생성하고, Controller 1개에 모든 엔드포인트 메서드를 합칩니다.
+ * 모든 응답은 JsonNode로 패스스루됩니다 (DTO 없음).
+ */
+ public CodeGenerationResult generate(List configs, boolean force) {
+ if (configs == null || configs.isEmpty()) {
+ throw new IllegalArgumentException("생성할 설정이 없습니다.");
+ }
+
+ String projectRoot = System.getProperty("user.dir");
+ String domain = configs.get(0).getDomainName();
+ String basePath = projectRoot + "/src/main/java/com/snp/batch/jobs/web/" + domain;
+
+ List servicePaths = new ArrayList<>();
+
+ for (BypassApiConfig config : configs) {
+ String endpointName = config.getEndpointName();
+ String servicePath = basePath + "/service/" + endpointName + "Service.java";
+
+ if (!force && Files.exists(Path.of(servicePath))) {
+ log.info("Service 파일 이미 존재, 스킵: {}", servicePath);
+ servicePaths.add(servicePath);
+ } else {
+ String serviceCode = generateServiceCode(domain, endpointName, config, config.getParams());
+ Path serviceFilePath = writeFile(servicePath, serviceCode, true);
+ servicePaths.add(serviceFilePath.toString());
+ }
+ }
+
+ // Controller: 모든 엔드포인트를 합치므로 항상 재생성
+ String controllerCode = generateControllerCode(domain, configs);
+ String domainCapitalized = capitalize(domain);
+ Path controllerFilePath = writeFile(
+ basePath + "/controller/" + domainCapitalized + "Controller.java", controllerCode, true);
+
+ log.info("코드 생성 완료 - domain: {}, endpoints: {}, controller: {}",
+ domain, configs.stream().map(BypassApiConfig::getEndpointName).toList(), controllerFilePath);
+
+ return CodeGenerationResult.builder()
+ .controllerPath(controllerFilePath.toString())
+ .servicePaths(servicePaths)
+ .message("코드 생성 완료. 서버를 재시작하면 새 API가 활성화됩니다.")
+ .build();
+ }
+
+ /**
+ * Service 코드 생성 (RAW 모드).
+ * BaseBypassService를 상속하여 fetchRawGet/fetchRawPost로 JsonNode를 반환합니다.
+ */
+ private String generateServiceCode(String domain, String endpointName,
+ BypassApiConfig config, List params) {
+ String packageName = BASE_PACKAGE + "." + domain + ".service";
+ String serviceClass = endpointName + "Service";
+ boolean isPost = "POST".equalsIgnoreCase(config.getHttpMethod());
+
+ String methodName = "get" + endpointName + "Data";
+ String fetchMethod = buildFetchMethodCall(config, params, isPost);
+ String methodParams = buildMethodParams(params);
+
+ return """
+ package {{PACKAGE}};
+
+ import com.fasterxml.jackson.databind.JsonNode;
+ import com.snp.batch.common.web.service.BaseBypassService;
+ import org.springframework.beans.factory.annotation.Qualifier;
+ import org.springframework.core.ParameterizedTypeReference;
+ import org.springframework.stereotype.Service;
+ import org.springframework.web.reactive.function.client.WebClient;
+
+ /**
+ * {{DISPLAY_NAME}} bypass 서비스
+ * 외부 Maritime API에서 데이터를 실시간 조회하여 JSON을 그대로 반환
+ */
+ @Service
+ public class {{SERVICE_CLASS}} extends BaseBypassService {
+
+ public {{SERVICE_CLASS}}(
+ @Qualifier("{{WEBCLIENT_BEAN}}") WebClient webClient) {
+ super(webClient, "{{EXTERNAL_PATH}}", "{{DISPLAY_NAME}}",
+ new ParameterizedTypeReference<>() {},
+ new ParameterizedTypeReference<>() {});
+ }
+
+ /**
+ * {{DISPLAY_NAME}} 데이터를 조회합니다.
+ */
+ public JsonNode {{METHOD_NAME}}({{METHOD_PARAMS}}) {
+ {{FETCH_METHOD}}
+ }
+ }
+ """
+ .replace("{{PACKAGE}}", packageName)
+ .replace("{{DISPLAY_NAME}}", config.getDisplayName())
+ .replace("{{SERVICE_CLASS}}", serviceClass)
+ .replace("{{WEBCLIENT_BEAN}}", config.getWebclientBean())
+ .replace("{{EXTERNAL_PATH}}", config.getExternalPath())
+ .replace("{{METHOD_NAME}}", methodName)
+ .replace("{{METHOD_PARAMS}}", methodParams)
+ .replace("{{FETCH_METHOD}}", fetchMethod);
+ }
+
+ /**
+ * Controller 코드 생성 (RAW 모드).
+ * 모든 엔드포인트가 ResponseEntity>를 반환합니다.
+ */
+ private String generateControllerCode(String domain, List configs) {
+ String packageName = BASE_PACKAGE + "." + domain + ".controller";
+ String servicePackage = BASE_PACKAGE + "." + domain + ".service";
+ String domainCap = capitalize(domain);
+ String requestMappingPath = "/api/" + domain;
+
+ // imports (중복 제거)
+ Set importSet = new LinkedHashSet<>();
+ importSet.add("import com.fasterxml.jackson.databind.JsonNode;");
+ importSet.add("import com.snp.batch.common.web.ApiResponse;");
+ importSet.add("import com.snp.batch.common.web.controller.BaseBypassController;");
+ importSet.add("import io.swagger.v3.oas.annotations.Operation;");
+ importSet.add("import io.swagger.v3.oas.annotations.Parameter;");
+ importSet.add("import io.swagger.v3.oas.annotations.tags.Tag;");
+ importSet.add("import lombok.RequiredArgsConstructor;");
+ importSet.add("import org.springframework.http.ResponseEntity;");
+ importSet.add("import org.springframework.web.bind.annotation.RequestMapping;");
+ importSet.add("import org.springframework.web.bind.annotation.RestController;");
+
+ boolean anyPost = configs.stream().anyMatch(c -> "POST".equalsIgnoreCase(c.getHttpMethod()));
+ boolean anyGet = configs.stream().anyMatch(c -> !"POST".equalsIgnoreCase(c.getHttpMethod()));
+ boolean anyPath = configs.stream()
+ .anyMatch(c -> c.getParams().stream().anyMatch(p -> "PATH".equalsIgnoreCase(p.getParamIn())));
+ boolean anyQuery = configs.stream()
+ .anyMatch(c -> c.getParams().stream().anyMatch(p -> "QUERY".equalsIgnoreCase(p.getParamIn())));
+ boolean anyBody = configs.stream()
+ .anyMatch(c -> c.getParams().stream().anyMatch(p -> "BODY".equalsIgnoreCase(p.getParamIn())));
+
+ if (anyPost) importSet.add("import org.springframework.web.bind.annotation.PostMapping;");
+ if (anyGet) importSet.add("import org.springframework.web.bind.annotation.GetMapping;");
+ if (anyPath) importSet.add("import org.springframework.web.bind.annotation.PathVariable;");
+ if (anyQuery) importSet.add("import org.springframework.web.bind.annotation.RequestParam;");
+ if (anyBody) importSet.add("import org.springframework.web.bind.annotation.RequestBody;");
+
+ for (BypassApiConfig config : configs) {
+ importSet.add("import " + servicePackage + "." + config.getEndpointName() + "Service;");
+ }
+
+ String importsStr = importSet.stream().collect(Collectors.joining("\n"));
+
+ // 필드 선언부
+ StringBuilder fields = new StringBuilder();
+ for (BypassApiConfig config : configs) {
+ String serviceClass = config.getEndpointName() + "Service";
+ String serviceField = Character.toLowerCase(serviceClass.charAt(0)) + serviceClass.substring(1);
+ fields.append(" private final ").append(serviceClass).append(" ").append(serviceField).append(";\n");
+ }
+
+ String tagPrefix = getTagPrefix(configs.get(0).getWebclientBean());
+ String tagDescription = tagPrefix + " " + domainCap + " bypass API";
+
+ // 엔드포인트 메서드 목록
+ StringBuilder methods = new StringBuilder();
+ for (BypassApiConfig config : configs) {
+ String endpointName = config.getEndpointName();
+ String serviceClass = endpointName + "Service";
+ String serviceField = Character.toLowerCase(serviceClass.charAt(0)) + serviceClass.substring(1);
+ boolean isPost = "POST".equalsIgnoreCase(config.getHttpMethod());
+
+ String mappingAnnotation = isPost ? "@PostMapping" : "@GetMapping";
+ String mappingPath = buildMappingPath(config.getParams(), config.getExternalPath());
+ String paramAnnotations = buildControllerParamAnnotations(config.getParams());
+ String serviceCallArgs = buildServiceCallArgs(config.getParams());
+ String methodName = "get" + endpointName + "Data";
+
+ methods.append("\n");
+ methods.append(" @Operation(\n");
+ methods.append(" summary = \"").append(config.getDisplayName()).append("\",\n");
+ String opDescription = (config.getDescription() != null && !config.getDescription().isEmpty())
+ ? config.getDescription()
+ : config.getDisplayName() + " 데이터를 요청하고 응답을 그대로 반환합니다.";
+ methods.append(" description = \"").append(opDescription).append("\"\n");
+ methods.append(" )\n");
+ methods.append(" ").append(mappingAnnotation).append(mappingPath).append("\n");
+ methods.append(" public ResponseEntity> ").append(methodName).append("(");
+ if (!paramAnnotations.isEmpty()) {
+ methods.append(paramAnnotations);
+ }
+ methods.append(") {\n");
+ methods.append(" return execute(() -> ").append(serviceField)
+ .append(".").append(methodName).append("(").append(serviceCallArgs).append("));\n");
+ methods.append(" }\n");
+ }
+
+ return "package " + packageName + ";\n\n"
+ + importsStr + "\n\n"
+ + "/**\n"
+ + " * " + domainCap + " bypass API\n"
+ + " * S&P Maritime API에서 데이터를 실시간 조회하여 JSON을 그대로 반환\n"
+ + " */\n"
+ + "@RestController\n"
+ + "@RequestMapping(\"" + requestMappingPath + "\")\n"
+ + "@RequiredArgsConstructor\n"
+ + "@Tag(name = \"" + domainCap + "\", description = \"" + tagDescription + "\")\n"
+ + "public class " + domainCap + "Controller extends BaseBypassController {\n\n"
+ + fields
+ + methods
+ + "}\n";
+ }
+
+ /**
+ * RAW fetch 메서드 호출 코드 생성
+ */
+ private String buildFetchMethodCall(BypassApiConfig config, List params, boolean isPost) {
+ List queryParams = params.stream()
+ .filter(p -> "QUERY".equalsIgnoreCase(p.getParamIn()))
+ .sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
+ .toList();
+
+ StringBuilder uriBuilder = new StringBuilder();
+ uriBuilder.append("uri -> uri.path(getApiPath())");
+ for (BypassApiParam p : queryParams) {
+ uriBuilder.append("\n .queryParam(\"")
+ .append(p.getParamName()).append("\", ").append(p.getParamName()).append(")");
+ }
+ uriBuilder.append("\n .build()");
+
+ if (isPost) {
+ BypassApiParam bodyParam = params.stream()
+ .filter(p -> "BODY".equalsIgnoreCase(p.getParamIn()))
+ .findFirst().orElse(null);
+ String bodyArg = bodyParam != null ? bodyParam.getParamName() : "null";
+ return "return fetchRawPost(" + bodyArg + ", " + uriBuilder + ");";
+ } else {
+ return "return fetchRawGet(" + uriBuilder + ");";
+ }
+ }
+
+ private String buildMethodParams(List params) {
+ return params.stream()
+ .sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
+ .map(p -> toJavaType(p.getParamType()) + " " + p.getParamName())
+ .collect(Collectors.joining(", "));
+ }
+
+ private String buildServiceCallArgs(List params) {
+ return params.stream()
+ .sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
+ .map(BypassApiParam::getParamName)
+ .collect(Collectors.joining(", "));
+ }
+
+ private String buildControllerParamAnnotations(List params) {
+ if (params.isEmpty()) {
+ return "";
+ }
+ return params.stream()
+ .sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
+ .map(p -> {
+ String description = p.getDescription() != null ? p.getDescription() : p.getParamName();
+ String javaType = toJavaType(p.getParamType());
+ String paramName = p.getParamName();
+ String example = (p.getExample() != null && !p.getExample().isEmpty())
+ ? p.getExample()
+ : getDefaultExample(p.getParamType());
+ return switch (p.getParamIn().toUpperCase()) {
+ case "PATH" -> "@Parameter(description = \"" + description + "\", example = \"" + example + "\")\n"
+ + " @PathVariable " + javaType + " " + paramName;
+ case "BODY" -> "@Parameter(description = \"" + description + "\", example = \"" + example + "\")\n"
+ + " @RequestBody " + javaType + " " + paramName;
+ default -> {
+ String required = Boolean.TRUE.equals(p.getRequired()) ? "true" : "false";
+ yield "@Parameter(description = \"" + description + "\", example = \"" + example + "\")\n"
+ + " @RequestParam(required = " + required + ") " + javaType + " " + paramName;
+ }
+ };
+ })
+ .collect(Collectors.joining(",\n "));
+ }
+
+ private String buildMappingPath(List params, String externalPath) {
+ String endpointSegment = "";
+ if (externalPath != null && !externalPath.isEmpty()) {
+ String[] segments = externalPath.split("/");
+ if (segments.length > 0) {
+ endpointSegment = "/" + segments[segments.length - 1];
+ }
+ }
+
+ List pathParams = params.stream()
+ .filter(p -> "PATH".equalsIgnoreCase(p.getParamIn()))
+ .sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
+ .toList();
+ String pathSuffix = pathParams.stream()
+ .map(p -> "{" + p.getParamName() + "}")
+ .collect(Collectors.joining("/", pathParams.isEmpty() ? "" : "/", ""));
+
+ String fullPath = endpointSegment + pathSuffix;
+ if (fullPath.isEmpty()) {
+ return "";
+ }
+ return "(\"" + fullPath + "\")";
+ }
+
+ private Path writeFile(String path, String content, boolean force) {
+ Path filePath = Path.of(path);
+ if (Files.exists(filePath) && !force) {
+ throw new IllegalStateException("파일이 이미 존재합니다: " + path + " (덮어쓰려면 force 옵션을 사용하세요)");
+ }
+ try {
+ Files.createDirectories(filePath.getParent());
+ Files.writeString(filePath, content, StandardCharsets.UTF_8);
+ log.info("파일 생성: {}", filePath);
+ } catch (IOException e) {
+ throw new RuntimeException("파일 쓰기 실패: " + path, e);
+ }
+ return filePath;
+ }
+
+ private String getTagPrefix(String webclientBean) {
+ if (webclientBean == null) {
+ return "[Ship API]";
+ }
+ return switch (webclientBean) {
+ case "maritimeAisApiWebClient" -> "[AIS API]";
+ case "maritimeServiceApiWebClient" -> "[Service API]";
+ default -> "[Ship API]";
+ };
+ }
+
+ private String getDefaultExample(String paramType) {
+ if (paramType == null) {
+ return "9876543";
+ }
+ return switch (paramType.toUpperCase()) {
+ case "INTEGER" -> "0";
+ case "LONG" -> "0";
+ case "BOOLEAN" -> "true";
+ default -> "9876543";
+ };
+ }
+
+ private String capitalize(String s) {
+ if (s == null || s.isEmpty()) {
+ return s;
+ }
+ return Character.toUpperCase(s.charAt(0)) + s.substring(1);
+ }
+
+ private String toJavaType(String paramType) {
+ if (paramType == null) {
+ return "String";
+ }
+ return switch (paramType.toUpperCase()) {
+ case "INTEGER" -> "Integer";
+ case "LONG" -> "Long";
+ case "BOOLEAN" -> "Boolean";
+ default -> "String";
+ };
+ }
+}
diff --git a/src/main/java/com/snp/batch/service/BypassConfigService.java b/src/main/java/com/snp/batch/service/BypassConfigService.java
new file mode 100644
index 0000000..5e4c0d7
--- /dev/null
+++ b/src/main/java/com/snp/batch/service/BypassConfigService.java
@@ -0,0 +1,189 @@
+package com.snp.batch.service;
+
+import com.snp.batch.global.dto.BypassConfigRequest;
+import com.snp.batch.global.dto.BypassConfigResponse;
+import com.snp.batch.global.dto.BypassParamDto;
+import com.snp.batch.global.model.BypassApiConfig;
+import com.snp.batch.global.model.BypassApiParam;
+import com.snp.batch.global.repository.BypassApiConfigRepository;
+import jakarta.persistence.EntityManager;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * BYPASS API 설정 CRUD 비즈니스 로직
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class BypassConfigService {
+
+ private final BypassApiConfigRepository configRepository;
+ private final EntityManager entityManager;
+
+ /**
+ * 설정 목록 조회
+ */
+ public List getConfigs() {
+ return configRepository.findAll().stream()
+ .map(this::toResponse)
+ .toList();
+ }
+
+ /**
+ * 설정 상세 조회
+ */
+ public BypassConfigResponse getConfig(Long id) {
+ BypassApiConfig config = configRepository.findById(id)
+ .orElseThrow(() -> new IllegalArgumentException("설정을 찾을 수 없습니다: " + id));
+ return toResponse(config);
+ }
+
+ /**
+ * 설정 등록
+ */
+ @Transactional
+ public BypassConfigResponse createConfig(BypassConfigRequest request) {
+ String endpointName = extractEndpointName(request.getExternalPath());
+ if (configRepository.existsByDomainNameAndEndpointName(request.getDomainName(), endpointName)) {
+ throw new IllegalArgumentException(
+ "이미 존재하는 도메인+엔드포인트 조합입니다: " + request.getDomainName() + "/" + endpointName);
+ }
+ BypassApiConfig config = toEntity(request);
+
+ if (request.getParams() != null) {
+ request.getParams().forEach(p -> {
+ BypassApiParam param = toParamEntity(p);
+ param.setConfig(config);
+ config.getParams().add(param);
+ });
+ }
+ return toResponse(configRepository.save(config));
+ }
+
+ /**
+ * 설정 수정
+ */
+ @Transactional
+ public BypassConfigResponse updateConfig(Long id, BypassConfigRequest request) {
+ BypassApiConfig config = configRepository.findById(id)
+ .orElseThrow(() -> new IllegalArgumentException("설정을 찾을 수 없습니다: " + id));
+
+ config.setDomainName(request.getDomainName());
+ config.setDisplayName(request.getDisplayName());
+ config.setWebclientBean(request.getWebclientBean());
+ config.setExternalPath(request.getExternalPath());
+ config.setHttpMethod(request.getHttpMethod());
+ config.setDescription(request.getDescription());
+
+ // params 교체: clear → flush(DELETE 실행) → 새로 추가
+ config.getParams().clear();
+ entityManager.flush();
+
+ if (request.getParams() != null) {
+ request.getParams().forEach(p -> {
+ BypassApiParam param = toParamEntity(p);
+ param.setConfig(config);
+ config.getParams().add(param);
+ });
+ }
+
+ return toResponse(configRepository.save(config));
+ }
+
+ /**
+ * 설정 삭제
+ */
+ @Transactional
+ public void deleteConfig(Long id) {
+ if (!configRepository.existsById(id)) {
+ throw new IllegalArgumentException("설정을 찾을 수 없습니다: " + id);
+ }
+ configRepository.deleteById(id);
+ }
+
+ /**
+ * 코드 생성 완료 마킹
+ */
+ @Transactional
+ public void markAsGenerated(Long id) {
+ BypassApiConfig config = configRepository.findById(id)
+ .orElseThrow(() -> new IllegalArgumentException("설정을 찾을 수 없습니다: " + id));
+ config.setGenerated(true);
+ config.setGeneratedAt(LocalDateTime.now());
+ configRepository.save(config);
+ }
+
+ // ---- private 헬퍼 메서드 ----
+
+ private BypassConfigResponse toResponse(BypassApiConfig config) {
+ return BypassConfigResponse.builder()
+ .id(config.getId())
+ .domainName(config.getDomainName())
+ .endpointName(config.getEndpointName())
+ .displayName(config.getDisplayName())
+ .webclientBean(config.getWebclientBean())
+ .externalPath(config.getExternalPath())
+ .httpMethod(config.getHttpMethod())
+ .description(config.getDescription())
+ .generated(config.getGenerated())
+ .generatedAt(config.getGeneratedAt())
+ .createdAt(config.getCreatedAt())
+ .updatedAt(config.getUpdatedAt())
+ .params(config.getParams().stream().map(this::toParamDto).toList())
+ .build();
+ }
+
+ private BypassApiConfig toEntity(BypassConfigRequest request) {
+ return BypassApiConfig.builder()
+ .domainName(request.getDomainName())
+ .endpointName(extractEndpointName(request.getExternalPath()))
+ .displayName(request.getDisplayName())
+ .webclientBean(request.getWebclientBean())
+ .externalPath(request.getExternalPath())
+ .httpMethod(request.getHttpMethod() != null ? request.getHttpMethod() : "GET")
+ .description(request.getDescription())
+ .build();
+ }
+
+ /**
+ * externalPath의 마지막 세그먼트를 endpointName으로 추출
+ */
+ private String extractEndpointName(String externalPath) {
+ if (externalPath == null || externalPath.isEmpty()) {
+ return "";
+ }
+ String[] segments = externalPath.split("/");
+ return segments[segments.length - 1];
+ }
+
+ private BypassApiParam toParamEntity(BypassParamDto dto) {
+ return BypassApiParam.builder()
+ .paramName(dto.getParamName())
+ .paramType(dto.getParamType() != null ? dto.getParamType() : "STRING")
+ .paramIn(dto.getParamIn() != null ? dto.getParamIn() : "QUERY")
+ .required(dto.getRequired() != null ? dto.getRequired() : true)
+ .description(dto.getDescription())
+ .sortOrder(dto.getSortOrder() != null ? dto.getSortOrder() : 0)
+ .example(dto.getExample())
+ .build();
+ }
+
+ private BypassParamDto toParamDto(BypassApiParam param) {
+ return BypassParamDto.builder()
+ .id(param.getId())
+ .paramName(param.getParamName())
+ .paramType(param.getParamType())
+ .paramIn(param.getParamIn())
+ .required(param.getRequired())
+ .description(param.getDescription())
+ .sortOrder(param.getSortOrder())
+ .example(param.getExample())
+ .build();
+ }
+}
diff --git a/src/main/java/com/snp/batch/service/ScreeningGuideService.java b/src/main/java/com/snp/batch/service/ScreeningGuideService.java
new file mode 100644
index 0000000..1b8f296
--- /dev/null
+++ b/src/main/java/com/snp/batch/service/ScreeningGuideService.java
@@ -0,0 +1,514 @@
+package com.snp.batch.service;
+
+import com.snp.batch.global.dto.screening.ChangeHistoryResponse;
+import com.snp.batch.global.dto.screening.CompanyInfoResponse;
+import com.snp.batch.global.dto.screening.ComplianceCategoryResponse;
+import com.snp.batch.global.dto.screening.ComplianceIndicatorResponse;
+import com.snp.batch.global.dto.screening.IndicatorStatusResponse;
+import com.snp.batch.global.dto.screening.MethodologyHistoryResponse;
+import com.snp.batch.global.dto.screening.RiskCategoryResponse;
+import com.snp.batch.global.dto.screening.RiskIndicatorResponse;
+import com.snp.batch.global.dto.screening.ShipInfoResponse;
+import com.snp.batch.global.model.screening.ChangeTypeLang;
+import com.snp.batch.global.model.screening.CompanyDetailInfo;
+import com.snp.batch.global.model.screening.ShipCountryCode;
+import com.snp.batch.global.model.screening.CompanyComplianceHistory;
+import com.snp.batch.global.model.screening.ComplianceIndicator;
+import com.snp.batch.global.model.screening.ComplianceIndicatorLang;
+import com.snp.batch.global.model.screening.MethodologyHistory;
+import com.snp.batch.global.model.screening.MethodologyHistoryLang;
+import com.snp.batch.global.model.screening.RiskIndicator;
+import com.snp.batch.global.model.screening.RiskIndicatorCategoryLang;
+import com.snp.batch.global.model.screening.RiskIndicatorLang;
+import com.snp.batch.global.model.screening.ShipComplianceHistory;
+import com.snp.batch.global.repository.screening.ChangeTypeLangRepository;
+import com.snp.batch.global.repository.screening.CompanyComplianceHistoryRepository;
+import com.snp.batch.global.repository.screening.CompanyDetailInfoRepository;
+import com.snp.batch.global.repository.screening.ComplianceIndicatorLangRepository;
+import com.snp.batch.global.repository.screening.ComplianceIndicatorRepository;
+import com.snp.batch.global.repository.screening.MethodologyHistoryLangRepository;
+import com.snp.batch.global.repository.screening.MethodologyHistoryRepository;
+import com.snp.batch.global.repository.screening.RiskIndicatorCategoryLangRepository;
+import com.snp.batch.global.repository.screening.RiskIndicatorLangRepository;
+import com.snp.batch.global.repository.screening.RiskIndicatorRepository;
+import com.snp.batch.global.repository.screening.ShipComplianceHistoryRepository;
+import com.snp.batch.global.repository.screening.ShipCountryCodeRepository;
+import com.snp.batch.global.repository.screening.ShipInfoMasterRepository;
+import com.snp.batch.global.repository.screening.ShipRiskDetailHistoryRepository;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class ScreeningGuideService {
+
+ private static final DateTimeFormatter DT_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+ private final RiskIndicatorRepository riskIndicatorRepo;
+ private final RiskIndicatorLangRepository riskIndicatorLangRepo;
+ private final RiskIndicatorCategoryLangRepository riskCategoryLangRepo;
+ private final ComplianceIndicatorRepository complianceIndicatorRepo;
+ private final ComplianceIndicatorLangRepository complianceIndicatorLangRepo;
+ private final MethodologyHistoryRepository methodologyHistoryRepo;
+ private final MethodologyHistoryLangRepository methodologyHistoryLangRepo;
+ private final ChangeTypeLangRepository changeTypeLangRepo;
+ private final ShipRiskDetailHistoryRepository shipRiskDetailHistoryRepo;
+ private final ShipComplianceHistoryRepository shipComplianceHistoryRepo;
+ private final CompanyComplianceHistoryRepository companyComplianceHistoryRepo;
+ private final ShipInfoMasterRepository shipInfoMasterRepo;
+ private final CompanyDetailInfoRepository companyDetailInfoRepo;
+ private final ShipCountryCodeRepository shipCountryCodeRepo;
+ private final JdbcTemplate jdbcTemplate;
+
+ /**
+ * 카테고리별 Risk 지표 목록 조회
+ *
+ * @param lang 언어 코드 (예: KO, EN)
+ * @return 카테고리별 Risk 지표 응답 목록
+ */
+ @Transactional(readOnly = true)
+ public List getRiskIndicators(String lang) {
+ Map catNameMap = riskCategoryLangRepo.findByLangCode(lang).stream()
+ .collect(Collectors.toMap(RiskIndicatorCategoryLang::getCategoryCode, RiskIndicatorCategoryLang::getCategoryName));
+
+ Map langMap = riskIndicatorLangRepo.findByLangCodeOrderByIndicatorIdAsc(lang).stream()
+ .collect(Collectors.toMap(RiskIndicatorLang::getIndicatorId, Function.identity()));
+
+ List indicators = riskIndicatorRepo.findAllByOrderByCategoryCodeAscSortOrderAsc();
+
+ Map> grouped = indicators.stream()
+ .collect(Collectors.groupingBy(RiskIndicator::getCategoryCode, LinkedHashMap::new, Collectors.toList()));
+
+ return grouped.entrySet().stream().map(entry -> {
+ String catCode = entry.getKey();
+ List indicatorResponses = entry.getValue().stream().map(ri -> {
+ RiskIndicatorLang langData = langMap.get(ri.getIndicatorId());
+ return RiskIndicatorResponse.builder()
+ .indicatorId(ri.getIndicatorId())
+ .fieldKey(ri.getFieldKey())
+ .fieldName(langData != null ? langData.getFieldName() : ri.getFieldKey())
+ .description(langData != null ? langData.getDescription() : "")
+ .conditionRed(langData != null ? langData.getConditionRed() : "")
+ .conditionAmber(langData != null ? langData.getConditionAmber() : "")
+ .conditionGreen(langData != null ? langData.getConditionGreen() : "")
+ .dataType(ri.getDataTypeCode())
+ .collectionNote(ri.getCollectionNote())
+ .build();
+ }).toList();
+
+ return RiskCategoryResponse.builder()
+ .categoryCode(catCode)
+ .categoryName(catNameMap.getOrDefault(catCode, catCode))
+ .indicators(indicatorResponses)
+ .build();
+ }).toList();
+ }
+
+ /**
+ * 카테고리별 Compliance 지표 목록 조회
+ *
+ * @param lang 언어 코드 (예: KO, EN)
+ * @param type 지표 유형 필터 (SHIP/COMPANY, null 또는 빈 문자열이면 전체)
+ * @return 카테고리별 Compliance 지표 응답 목록
+ */
+ @Transactional(readOnly = true)
+ public List getComplianceIndicators(String lang, String type) {
+ List indicators = (type != null && !type.isBlank())
+ ? complianceIndicatorRepo.findByIndicatorTypeOrderBySortOrderAsc(type)
+ : complianceIndicatorRepo.findAllByOrderBySortOrderAsc();
+
+ Map langMap = complianceIndicatorLangRepo.findByLangCode(lang).stream()
+ .collect(Collectors.toMap(ComplianceIndicatorLang::getIndicatorId, Function.identity()));
+
+ Map> grouped = indicators.stream()
+ .collect(Collectors.groupingBy(ComplianceIndicator::getCategory, LinkedHashMap::new, Collectors.toList()));
+
+ return grouped.entrySet().stream().map(entry -> {
+ List indicatorResponses = entry.getValue().stream().map(ci -> {
+ ComplianceIndicatorLang langData = langMap.get(ci.getIndicatorId());
+ return ComplianceIndicatorResponse.builder()
+ .indicatorId(ci.getIndicatorId())
+ .fieldKey(ci.getFieldKey())
+ .fieldName(langData != null ? langData.getFieldName() : ci.getFieldKey())
+ .description(langData != null ? langData.getDescription() : "")
+ .conditionRed(langData != null ? langData.getConditionRed() : "")
+ .conditionAmber(langData != null ? langData.getConditionAmber() : "")
+ .conditionGreen(langData != null ? langData.getConditionGreen() : "")
+ .dataType(ci.getDataTypeCode())
+ .collectionNote(ci.getCollectionNote())
+ .build();
+ }).toList();
+
+ return ComplianceCategoryResponse.builder()
+ .category(entry.getKey())
+ .indicatorType(type)
+ .indicators(indicatorResponses)
+ .build();
+ }).toList();
+ }
+
+ /**
+ * 방법론 변경 이력 조회
+ *
+ * @param lang 언어 코드 (예: KO, EN)
+ * @return 방법론 변경 이력 응답 목록
+ */
+ @Transactional(readOnly = true)
+ public List getMethodologyHistory(String lang) {
+ Map changeTypeMap = changeTypeLangRepo.findByLangCode(lang).stream()
+ .collect(Collectors.toMap(ChangeTypeLang::getTypeCode, ChangeTypeLang::getTypeName));
+
+ Map langMap = methodologyHistoryLangRepo.findByLangCode(lang).stream()
+ .collect(Collectors.toMap(MethodologyHistoryLang::getHistoryId, Function.identity()));
+
+ List histories = methodologyHistoryRepo.findAllByOrderByChangeDateDescSortOrderAsc();
+
+ return histories.stream().map(mh -> {
+ MethodologyHistoryLang langData = langMap.get(mh.getHistoryId());
+ return MethodologyHistoryResponse.builder()
+ .historyId(mh.getHistoryId())
+ .changeDate(mh.getChangeDate() != null ? mh.getChangeDate().toString() : "")
+ .changeType(changeTypeMap.getOrDefault(mh.getChangeTypeCode(), mh.getChangeTypeCode()))
+ .updateTitle(langData != null ? langData.getUpdateTitle() : "")
+ .description(langData != null ? langData.getDescription() : "")
+ .collectionNote(mh.getCollectionNote())
+ .build();
+ }).toList();
+ }
+
+ /**
+ * 선박 위험지표 값 변경 이력 조회
+ *
+ * @param imoNo IMO 번호
+ * @param lang 언어 코드 (예: KO, EN)
+ * @return 변경 이력 응답 목록
+ */
+ @Transactional(readOnly = true)
+ public List getShipRiskDetailHistory(String imoNo, String lang) {
+ Map fieldNameMap = getRiskFieldNameMap(lang);
+ Map sortOrderMap = getRiskSortOrderMap();
+ List rows = shipRiskDetailHistoryRepo.findRiskHistoryWithNarrative(imoNo);
+ return rows.stream().map(row -> {
+ String colName = (String) row[3];
+ return ChangeHistoryResponse.builder()
+ .rowIndex(((Number) row[0]).longValue())
+ .searchKey((String) row[1])
+ .lastModifiedDate(row[2] != null ? row[2].toString().substring(0, Math.min(row[2].toString().length(), 19)) : "")
+ .changedColumnName(colName)
+ .beforeValue((String) row[4])
+ .afterValue((String) row[5])
+ .narrative((String) row[6])
+ .prevNarrative((String) row[7])
+ .fieldName(fieldNameMap.getOrDefault(colName, colName))
+ .sortOrder(sortOrderMap.getOrDefault(colName, Integer.MAX_VALUE))
+ .build();
+ }).toList();
+ }
+
+ /**
+ * 선박 제재 값 변경 이력 조회
+ *
+ * @param imoNo IMO 번호
+ * @param lang 언어 코드 (예: KO, EN)
+ * @return 변경 이력 응답 목록
+ */
+ @Transactional(readOnly = true)
+ public List getShipComplianceHistory(String imoNo, String lang) {
+ Map fieldNameMap = getComplianceFieldNameMap(lang, "SHIP");
+ Map sortOrderMap = getComplianceSortOrderMap("SHIP");
+ return shipComplianceHistoryRepo.findByImoNoOrderByLastModifiedDateDesc(imoNo).stream()
+ .map(h -> ChangeHistoryResponse.builder()
+ .rowIndex(h.getRowIndex())
+ .searchKey(h.getImoNo())
+ .lastModifiedDate(h.getLastModifiedDate() != null ? h.getLastModifiedDate().format(DT_FORMAT) : "")
+ .changedColumnName(h.getChangedColumnName())
+ .beforeValue(h.getBeforeValue())
+ .afterValue(h.getAfterValue())
+ .fieldName(fieldNameMap.getOrDefault(h.getChangedColumnName(), h.getChangedColumnName()))
+ .sortOrder(sortOrderMap.getOrDefault(h.getChangedColumnName(), Integer.MAX_VALUE))
+ .build())
+ .toList();
+ }
+
+ /**
+ * 회사 제재 값 변경 이력 조회
+ *
+ * @param companyCode 회사 코드
+ * @param lang 언어 코드 (예: KO, EN)
+ * @return 변경 이력 응답 목록
+ */
+ @Transactional(readOnly = true)
+ public List getCompanyComplianceHistory(String companyCode, String lang) {
+ Map fieldNameMap = getComplianceFieldNameMap(lang, "COMPANY");
+ Map sortOrderMap = getComplianceSortOrderMap("COMPANY");
+ return companyComplianceHistoryRepo.findByCompanyCodeOrderByLastModifiedDateDesc(companyCode).stream()
+ .map(h -> ChangeHistoryResponse.builder()
+ .rowIndex(h.getRowIndex())
+ .searchKey(h.getCompanyCode())
+ .lastModifiedDate(h.getLastModifiedDate() != null ? h.getLastModifiedDate().format(DT_FORMAT) : "")
+ .changedColumnName(h.getChangedColumnName())
+ .beforeValue(h.getBeforeValue())
+ .afterValue(h.getAfterValue())
+ .fieldName(fieldNameMap.getOrDefault(h.getChangedColumnName(), h.getChangedColumnName()))
+ .sortOrder(sortOrderMap.getOrDefault(h.getChangedColumnName(), Integer.MAX_VALUE))
+ .build())
+ .toList();
+ }
+
+ /**
+ * 선박 기본 정보 조회
+ */
+ @Transactional(readOnly = true)
+ public ShipInfoResponse getShipInfo(String imoNo) {
+ return shipInfoMasterRepo.findByImoNo(imoNo)
+ .map(s -> ShipInfoResponse.builder()
+ .imoNo(s.getImoNo())
+ .shipName(s.getShipName())
+ .shipStatus(s.getShipStatus())
+ .nationalityCode(s.getNationalityCode())
+ .nationalityIsoCode(resolveIsoTwoCode(s.getNationalityCode()))
+ .nationality(s.getNationality())
+ .shipType(s.getShipType())
+ .dwt(s.getDwt())
+ .gt(s.getGt())
+ .buildYear(s.getBuildYear())
+ .mmsiNo(s.getMmsiNo())
+ .callSign(s.getCallSign())
+ .shipTypeGroup(s.getShipTypeGroup())
+ .build())
+ .orElse(null);
+ }
+
+ /**
+ * 회사 기본 정보 조회
+ */
+ @Transactional(readOnly = true)
+ public CompanyInfoResponse getCompanyInfo(String companyCode) {
+ return companyDetailInfoRepo.findByCompanyCode(companyCode)
+ .map(c -> {
+ String parentCompanyName = null;
+ if (c.getParentCompanyCode() != null && !c.getParentCompanyCode().isBlank()) {
+ parentCompanyName = companyDetailInfoRepo.findByCompanyCode(c.getParentCompanyCode())
+ .map(CompanyDetailInfo::getFullName)
+ .orElse("UNKNOWN");
+ }
+ return CompanyInfoResponse.builder()
+ .companyCode(c.getCompanyCode())
+ .fullName(c.getFullName())
+ .abbreviation(c.getAbbreviation())
+ .status(c.getStatus())
+ .parentCompanyCode(c.getParentCompanyCode())
+ .parentCompanyName(parentCompanyName)
+ .registrationCountry(c.getRegistrationCountry())
+ .registrationCountryCode(c.getRegistrationCountryCode())
+ .registrationCountryIsoCode(resolveIsoTwoCode(c.getRegistrationCountryCode()))
+ .controlCountry(c.getControlCountry())
+ .controlCountryCode(c.getControlCountryCode())
+ .controlCountryIsoCode(resolveIsoTwoCode(c.getControlCountryCode()))
+ .foundedDate(c.getFoundedDate())
+ .email(c.getEmail())
+ .phone(c.getPhone())
+ .website(c.getWebsite())
+ .build();
+ })
+ .orElse(null);
+ }
+
+ /**
+ * 선박 현재 Risk 지표 상태 조회
+ */
+ @Transactional(readOnly = true)
+ public List getShipRiskStatus(String imoNo, String lang) {
+ Map fieldNameMap = getRiskFieldNameMap(lang);
+ Map sortOrderMap = getRiskSortOrderMap();
+ Map categoryMap = getRiskCategoryMap(lang);
+
+ try {
+ Map row = jdbcTemplate.queryForMap(
+ "SELECT * FROM std_snp_svc.tb_ship_risk_detail_info WHERE imo_no = ?", imoNo);
+
+ List result = new ArrayList<>();
+ for (Map.Entry entry : sortOrderMap.entrySet()) {
+ String colName = entry.getKey();
+ Object codeVal = row.get(colName);
+ String descColName = "ais_up_imo_desc".equals(colName) ? "ais_up_imo_desc_val" : colName + "_desc";
+ Object descVal = row.get(descColName);
+
+ result.add(IndicatorStatusResponse.builder()
+ .columnName(colName)
+ .fieldName(fieldNameMap.getOrDefault(colName, colName))
+ .category(categoryMap.getOrDefault(colName, ""))
+ .value(codeVal != null ? codeVal.toString() : null)
+ .narrative(descVal != null ? descVal.toString() : null)
+ .sortOrder(entry.getValue())
+ .build());
+ }
+ result.sort(Comparator.comparingInt(IndicatorStatusResponse::getSortOrder));
+ return result;
+ } catch (EmptyResultDataAccessException e) {
+ return List.of();
+ }
+ }
+
+ /**
+ * 선박 현재 Compliance 상태 조회
+ */
+ @Transactional(readOnly = true)
+ public List getShipComplianceStatus(String imoNo, String lang) {
+ Map fieldNameMap = getComplianceFieldNameMap(lang, "SHIP");
+ Map sortOrderMap = getComplianceSortOrderMap("SHIP");
+ Map categoryMap = getComplianceCategoryMap("SHIP");
+
+ try {
+ Map row = jdbcTemplate.queryForMap(
+ "SELECT * FROM std_snp_svc.tb_ship_compliance_info WHERE imo_no = ?", imoNo);
+
+ List result = new ArrayList<>();
+ for (Map.Entry entry : sortOrderMap.entrySet()) {
+ String colName = entry.getKey();
+ Object codeVal = row.get(colName);
+
+ result.add(IndicatorStatusResponse.builder()
+ .columnName(colName)
+ .fieldName(fieldNameMap.getOrDefault(colName, colName))
+ .category(categoryMap.getOrDefault(colName, ""))
+ .value(codeVal != null ? codeVal.toString() : null)
+ .sortOrder(entry.getValue())
+ .build());
+ }
+ result.sort(Comparator.comparingInt(IndicatorStatusResponse::getSortOrder));
+ return result;
+ } catch (EmptyResultDataAccessException e) {
+ return List.of();
+ }
+ }
+
+ /**
+ * 회사 현재 Compliance 상태 조회
+ */
+ @Transactional(readOnly = true)
+ public List getCompanyComplianceStatus(String companyCode, String lang) {
+ Map fieldNameMap = getComplianceFieldNameMap(lang, "COMPANY");
+ Map sortOrderMap = getComplianceSortOrderMap("COMPANY");
+ Map categoryMap = getComplianceCategoryMap("COMPANY");
+
+ try {
+ Map row = jdbcTemplate.queryForMap(
+ "SELECT * FROM std_snp_svc.tb_company_compliance_info WHERE company_cd = ?", companyCode);
+
+ List result = new ArrayList<>();
+ for (Map.Entry entry : sortOrderMap.entrySet()) {
+ String colName = entry.getKey();
+ Object codeVal = row.get(colName);
+
+ result.add(IndicatorStatusResponse.builder()
+ .columnName(colName)
+ .fieldName(fieldNameMap.getOrDefault(colName, colName))
+ .category(categoryMap.getOrDefault(colName, ""))
+ .value(codeVal != null ? codeVal.toString() : null)
+ .sortOrder(entry.getValue())
+ .build());
+ }
+ result.sort(Comparator.comparingInt(IndicatorStatusResponse::getSortOrder));
+ return result;
+ } catch (EmptyResultDataAccessException e) {
+ return List.of();
+ }
+ }
+
+ private String resolveIsoTwoCode(String shipCountryCode) {
+ if (shipCountryCode == null || shipCountryCode.isBlank()) return null;
+ return shipCountryCodeRepo.findByShipCountryCode(shipCountryCode)
+ .map(ShipCountryCode::getIsoTwoCode)
+ .orElse(null);
+ }
+
+ /**
+ * Risk 지표 컬럼명 → 필드명 매핑 조회
+ */
+ private Map getRiskFieldNameMap(String lang) {
+ Map langMap = riskIndicatorLangRepo.findByLangCodeOrderByIndicatorIdAsc(lang).stream()
+ .collect(Collectors.toMap(RiskIndicatorLang::getIndicatorId, RiskIndicatorLang::getFieldName));
+ return riskIndicatorRepo.findAllByOrderByCategoryCodeAscSortOrderAsc().stream()
+ .filter(ri -> ri.getColumnName() != null)
+ .collect(Collectors.toMap(
+ RiskIndicator::getColumnName,
+ ri -> langMap.getOrDefault(ri.getIndicatorId(), ri.getFieldKey()),
+ (a, b) -> a));
+ }
+
+ private Map getRiskCategoryMap(String lang) {
+ Map catNameMap = riskCategoryLangRepo.findByLangCode(lang).stream()
+ .collect(Collectors.toMap(RiskIndicatorCategoryLang::getCategoryCode, RiskIndicatorCategoryLang::getCategoryName));
+ return riskIndicatorRepo.findAllByOrderByCategoryCodeAscSortOrderAsc().stream()
+ .filter(ri -> ri.getColumnName() != null)
+ .collect(Collectors.toMap(
+ RiskIndicator::getColumnName,
+ ri -> catNameMap.getOrDefault(ri.getCategoryCode(), ri.getCategoryCode()),
+ (a, b) -> a));
+ }
+
+ private Map getRiskSortOrderMap() {
+ return riskIndicatorRepo.findAllByOrderByCategoryCodeAscSortOrderAsc().stream()
+ .filter(ri -> ri.getColumnName() != null)
+ .collect(Collectors.toMap(
+ RiskIndicator::getColumnName,
+ RiskIndicator::getSortOrder,
+ (a, b) -> a));
+ }
+
+ /**
+ * Compliance 지표 컬럼명 → 필드명 매핑 조회
+ */
+ private Map getComplianceFieldNameMap(String lang, String type) {
+ Map langMap = complianceIndicatorLangRepo.findByLangCode(lang).stream()
+ .collect(Collectors.toMap(ComplianceIndicatorLang::getIndicatorId, ComplianceIndicatorLang::getFieldName));
+ List indicators = (type != null && !type.isBlank())
+ ? complianceIndicatorRepo.findByIndicatorTypeOrderBySortOrderAsc(type)
+ : complianceIndicatorRepo.findAllByOrderBySortOrderAsc();
+ return indicators.stream()
+ .filter(ci -> ci.getColumnName() != null)
+ .collect(Collectors.toMap(
+ ComplianceIndicator::getColumnName,
+ ci -> langMap.getOrDefault(ci.getIndicatorId(), ci.getFieldKey()),
+ (a, b) -> a));
+ }
+
+ private Map getComplianceCategoryMap(String type) {
+ List indicators = (type != null && !type.isBlank())
+ ? complianceIndicatorRepo.findByIndicatorTypeOrderBySortOrderAsc(type)
+ : complianceIndicatorRepo.findAllByOrderBySortOrderAsc();
+ return indicators.stream()
+ .filter(ci -> ci.getColumnName() != null)
+ .collect(Collectors.toMap(
+ ComplianceIndicator::getColumnName,
+ ComplianceIndicator::getCategory,
+ (a, b) -> a));
+ }
+
+ private Map getComplianceSortOrderMap(String type) {
+ List indicators = (type != null && !type.isBlank())
+ ? complianceIndicatorRepo.findByIndicatorTypeOrderBySortOrderAsc(type)
+ : complianceIndicatorRepo.findAllByOrderBySortOrderAsc();
+ return indicators.stream()
+ .filter(ci -> ci.getColumnName() != null)
+ .collect(Collectors.toMap(
+ ComplianceIndicator::getColumnName,
+ ComplianceIndicator::getSortOrder,
+ (a, b) -> a));
+ }
+}