chore: 시스템 구동에 불필요한 잔재 파일 일괄 삭제
Deploy momo-erp / deploy (push) Successful in 49s

삭제 (FITO 잔재 / 미사용 스크립트):
- dev_git_only.{bat,sh}, run-windows.bat, stop-windows.bat
- start-{debug,dev,dev-full,dev-full-win,devlocal-full,docker-linux,prod-full}.sh, start.sh
- setup.sh, smart-logs.sh, verify-build.sh, quick-rebuild.sh, quick-update-jsp.sh
- build-mac.sh, build-windows.bat, compile_only.sh
- docker-compose.{debug,localdev,win}.yml, Dockerfile.win, dockerfilelocal.dev
- hin, pace_ilshinplm-ilshin (정체불명)
- AGENTS.md, BOM_SEQ_DRAG_DROP.md (FITO 잔재 문서)
- test_contract_*.{html,md} (FITO 계약 테스트)
- cookies.txt (테스트 쿠키 — 보안)
- env.{development,production}.example, .env.example (.env.production.example 와 중복)
- tsconfig.tsbuildinfo (빌드 산출물)

남은 핵심 파일:
- 빌드/런: package.json, tsconfig.json, next.config.ts, postcss.config.mjs, eslint.config.mjs
- 도커: Dockerfile, Dockerfile.dev, docker-compose.{prod,dev}.yml
- 환경: .env.production.example, .env.momo.example
- 가이드: README.md, DOCKER_SETUP.md, SETTING_GUIDE.txt, CICD_SETUP.md, CLAUDE.md
This commit is contained in:
chpark
2026-04-26 01:14:57 +09:00
parent 95129cf606
commit 0ba97294eb
37 changed files with 123 additions and 3089 deletions
-8
View File
@@ -1,8 +0,0 @@
# Copy this file to .env (local dev) or .env.production (prod) and fill in values.
# These files are gitignored — never commit real credentials.
DB_HOST=183.99.177.40
DB_PORT=5432
DB_NAME=distribution
DB_USERNAME=postgres
DB_PASSWORD=changeme
-5
View File
@@ -1,5 +0,0 @@
<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
<!-- END:nextjs-agent-rules -->
-166
View File
@@ -1,166 +0,0 @@
# BOM 구조 관리 SEQ 드래그앤드롭 기능
## 개요
BOM(Bill of Materials) 구조 관리 화면에서 PART 항목들을 드래그앤드롭으로 순서를 변경할 수 있는 기능입니다.
## 핵심 기능
- **LEVEL별 SEQ 관리**: 각 LEVEL(PARENT_OBJID) 내에서 SEQ를 1, 2, 3... 순차적으로 관리
- **드래그앤드롭**: jQuery UI Sortable을 이용한 직관적인 순서 변경
- **자동 저장**: 드래그 완료 시 자동으로 DB에 저장 및 페이지 새로고침
- **엑셀 업로드**: 업로드 순서대로 SEQ 자동 부여
## 구현 내용
### 1. 데이터베이스 (partMng.xml)
```sql
-- PART 추가 시 자동 SEQ 부여 (LEVEL별 MAX + 1)
SEQ = COALESCE(
(SELECT MAX(seq) + 1
FROM BOM_PART_QTY
WHERE bom_report_objid = #{BOM_REPORT_OBJID}
AND COALESCE(parent_objid, '') = COALESCE(#{PARENT_OBJID}, '')),
1
)
-- 엑셀 업로드 시 순서대로 SEQ 부여
SEQ = ROW_NUMBER() OVER (
PARTITION BY BOM_REPORT_OBJID, PARENT_OBJID
ORDER BY T.seq ASC
)
-- 드래그앤드롭 후 SEQ 일괄 업데이트
UPDATE BOM_PART_QTY
SET seq = CASE child_objid
WHEN #{item.CHILD_OBJID} THEN #{item.SEQ}::numeric
...
END
WHERE child_objid IN (...)
```
### 2. 백엔드 (Java/Spring)
**PartMngService.java**
- `structureDragDropSeqSave()`: JSON 파싱 및 SEQ 일괄 업데이트
- Gson을 이용한 JSON → List<Map> 변환
- 트랜잭션 처리 (commit/rollback)
**PartMngController.java**
- `POST /partMng/structureDragDropSeqSave.do`: SEQ 저장 API
### 3. 프론트엔드 (structurePopupLeft.jsp)
**jQuery UI Sortable 적용**
```javascript
$("#structurePopupTable2").sortable({
items: "tr.sortable-row",
axis: "y",
tolerance: "pointer",
start: function(event, ui) {
// 드래그 시작: 같은 그룹만 허용
var dragGroupKey = ui.item.attr("data-group-key");
ui.item.data("dragGroupKey", dragGroupKey);
},
stop: function(event, ui) {
// 드래그 종료: 위치 검증 및 저장
var dragGroupKey = ui.item.data("dragGroupKey");
var $prev = ui.item.prev("tr.sortable-row");
var $next = ui.item.next("tr.sortable-row");
// 같은 LEVEL 내에서만 이동 가능
if (isValidPosition) {
saveDragDropSeq(dragGroupKey);
} else {
$("#structurePopupTable2").sortable("cancel");
}
}
});
```
**SEQ 저장 및 새로고침**
```javascript
function saveDragDropSeq(groupKey) {
// 같은 그룹의 모든 항목 SEQ 수집
var seqList = [];
$("#structurePopupTable2 tr.sortable-row").each(function() {
if ($(this).attr("data-group-key") === groupKey) {
seqList.push({
CHILD_OBJID: childObjid,
SEQ: seqList.length + 1
});
}
});
// AJAX로 저장
$.ajax({
url: "/partMng/structureDragDropSeqSave.do",
data: { seqList: JSON.stringify(seqList) },
success: function(data) {
if (data.result) {
location.reload(); // 자동 새로고침
}
}
});
}
```
## 주요 특징
### 1. LEVEL별 독립적인 SEQ 관리
- LEVEL 1: SEQ = 1, 2, 3, 4...
- LEVEL 2: SEQ = 1, 2, 3, 4...
- LEVEL 3: SEQ = 1, 2, 3, 4...
### 2. 드래그 제약 조건
- **같은 LEVEL 내에서만** 순서 변경 가능
- 다른 LEVEL로 이동 시도 시 자동 취소
- 시각적 피드백 (disabled 클래스)
### 3. 자동 저장 및 반영
- 드래그 완료 즉시 DB 저장
- 성공 메시지 표시 (0.8초)
- 자동 페이지 새로고침으로 변경 사항 즉시 반영
## 기존 데이터 마이그레이션
**파일**: `db/migration_seq_reorder.sql`
전역 시퀀스로 부여된 기존 SEQ를 LEVEL별로 재정렬:
```bash
psql -U postgres -d ilshin -f db/migration_seq_reorder.sql
```
## 수정된 파일 목록
1. `src/com/pms/mapper/partMng.xml` - SQL 쿼리 수정
2. `src/com/pms/service/PartMngService.java` - 비즈니스 로직
3. `src/com/pms/controller/PartMngController.java` - API 엔드포인트
4. `WebContent/WEB-INF/view/partMng/structurePopupLeft.jsp` - UI 구현
5. `db/migration_seq_reorder.sql` - 마이그레이션 스크립트
## 사용 방법
1. BOM 구조 관리 화면 접속
2. 같은 LEVEL의 PART 항목을 드래그
3. 원하는 위치에 드롭
4. 자동 저장 및 페이지 새로고침
5. 변경된 순서 확인
## 트러블슈팅
### 드래그가 안 될 때
- jQuery UI 라이브러리 로드 확인
- 브라우저 콘솔에서 에러 확인
- `data-group-key` 속성 확인
### 저장이 안 될 때
- 서버 콘솔에서 로그 확인
- JSON 파싱 오류 확인
- DB 트랜잭션 상태 확인
### 순서가 이상할 때
- 마이그레이션 스크립트 실행 확인
- SEQ 중복 여부 확인
- LEVEL별 SEQ 범위 확인
## 참고 사항
- jQuery UI Sortable 1.12.1 사용
- Gson 2.3.1로 JSON 파싱
- PostgreSQL Recursive CTE로 계층 구조 조회
- 트랜잭션 처리로 데이터 무결성 보장
-50
View File
@@ -1,50 +0,0 @@
# 윈도우용 PLM 애플리케이션 Dockerfile
FROM tomcat:7.0.94-jre7-alpine
# 메타데이터
LABEL maintainer="PLM Development Team"
LABEL description="PLM Application for Windows Environment"
LABEL version="1.0"
# 작업 디렉토리 설정
WORKDIR /usr/local/tomcat
# 필수 패키지 설치 (curl 포함)
RUN apk add --no-cache curl tzdata
# 환경 변수 설정
ENV CATALINA_HOME=/usr/local/tomcat
ENV CATALINA_BASE=/usr/local/tomcat
ENV JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms512m -Xmx1024m"
ENV TZ=Asia/Seoul
# 타임존 설정 (서울)
RUN cp /usr/share/zoneinfo/Asia/Seoul /etc/localtime && \
echo "Asia/Seoul" > /etc/timezone
# 기본 Tomcat 애플리케이션 제거
RUN rm -rf /usr/local/tomcat/webapps/*
# 애플리케이션 복사
COPY WebContent/ /usr/local/tomcat/webapps/ROOT/
COPY tomcat-conf/context.xml /usr/local/tomcat/conf/
# Configure Tomcat Connector for UTF-8 URI encoding
RUN sed -i 's/<Connector port="8080"/<Connector port="8080" URIEncoding="UTF-8"/g' /usr/local/tomcat/conf/server.xml
# 로그 디렉토리 생성
RUN mkdir -p /usr/local/tomcat/logs
# 권한 설정
RUN chmod -R 755 /usr/local/tomcat/webapps/ROOT && \
chmod 644 /usr/local/tomcat/conf/context.xml
# 포트 노출
EXPOSE 8080
# 개선된 헬스체크 (윈도우 환경 고려)
HEALTHCHECK --interval=30s --timeout=15s --start-period=90s --retries=5 \
CMD curl -f http://localhost:8080/ROOT/ || curl -f http://localhost:8080/ || exit 1
# 실행 명령
CMD ["catalina.sh", "run"]
-168
View File
@@ -1,168 +0,0 @@
#!/bin/bash
# macOS 전용 Java 애플리케이션 빌드 스크립트
# Windows build-windows.bat의 macOS 버전
set -e # 오류 발생 시 스크립트 중단
echo "==============================================="
echo " Java Application Build for macOS"
echo "==============================================="
echo ""
# macOS 확인
if [[ "$(uname -s)" != "Darwin" ]]; then
echo "❌ ERROR: This script is designed for macOS only."
echo "Current OS: $(uname -s)"
exit 1
fi
echo "🍎 Running on macOS..."
echo "[1] Checking Java environment..."
# Java 런타임 확인
if ! command -v java &> /dev/null; then
echo "❌ ERROR: Java not found in PATH"
echo "Please install Java and add to PATH"
exit 1
fi
# Java 컴파일러 확인
if ! command -v javac &> /dev/null; then
echo "❌ ERROR: Java compiler not found"
echo "Please install JDK"
exit 1
fi
# Java 버전 표시
java_version=$(java -version 2>&1 | head -n 1 | cut -d'"' -f2)
javac_version=$(javac -version 2>&1 | cut -d' ' -f2)
echo "✅ Java Runtime: $java_version"
echo "✅ Java Compiler: $javac_version"
echo "Java environment OK"
echo "[2] Cleaning previous build..."
if [ -d "WebContent/WEB-INF/classes" ]; then
rm -rf WebContent/WEB-INF/classes
fi
echo "✅ Previous build cleaned"
echo "[3] Creating directories..."
mkdir -p WebContent/WEB-INF/classes
mkdir -p WebContent/WEB-INF/lib
mkdir -p logs
echo "✅ Directories created"
echo "[4] Checking libraries..."
SERVLET_JAR1="WebContent/WEB-INF/lib/javax.servlet-api-4.0.1.jar"
SERVLET_JAR2="WebContent/WEB-INF/lib/servlet-api.jar"
if [ ! -f "$SERVLET_JAR1" ] && [ ! -f "$SERVLET_JAR2" ]; then
echo "❌ ERROR: Servlet API JAR not found"
echo "Need: $SERVLET_JAR1 or $SERVLET_JAR2"
echo ""
echo "💡 You can download it from:"
echo " - Maven Central Repository"
echo " - Tomcat distribution's 'lib' folder"
exit 1
fi
if [ -f "$SERVLET_JAR1" ]; then
echo "✅ Found: $SERVLET_JAR1"
elif [ -f "$SERVLET_JAR2" ]; then
echo "✅ Found: $SERVLET_JAR2"
fi
echo "Libraries OK"
echo "[5] Setting classpath..."
CLASSPATH="src:WebContent/WEB-INF/lib/*"
echo "📋 Classpath: $CLASSPATH"
echo "[6] Finding Java files..."
# 임시 파일 생성
JAVA_SOURCES_FILE=$(mktemp)
trap "rm -f $JAVA_SOURCES_FILE" EXIT
# Java 파일 찾기
find src -name "*.java" -type f > "$JAVA_SOURCES_FILE"
java_count=$(wc -l < "$JAVA_SOURCES_FILE" | tr -d ' ')
if [ "$java_count" -eq 0 ]; then
echo "⚠️ WARNING: No Java files found"
else
echo "✅ Found $java_count Java files"
fi
echo "[7] Compiling Java files..."
if [ -s "$JAVA_SOURCES_FILE" ]; then
echo "⚙️ Starting compilation..."
# Java 파일 컴파일 (Java 7 호환성 유지)
javac \
-encoding UTF-8 \
-source 1.7 \
-target 1.7 \
-d WebContent/WEB-INF/classes \
-cp "$CLASSPATH" \
-Xlint:unchecked \
-Xlint:deprecation \
@"$JAVA_SOURCES_FILE"
if [ $? -eq 0 ]; then
echo "✅ Compilation completed successfully"
else
echo "❌ ERROR: Compilation failed"
exit 1
fi
else
echo "️ No Java files to compile"
fi
echo "[8] Copying resources..."
resource_count=0
# 리소스 파일 복사 (XML, Properties, SQL)
find src -type f \( -name "*.xml" -o -name "*.properties" -o -name "*.sql" \) -print0 | \
while IFS= read -r -d '' source_file; do
# 'src/' 접두사를 제거하여 상대 경로 생성
relative_path="${source_file#src/}"
target_file="WebContent/WEB-INF/classes/$relative_path"
# 대상 디렉토리 생성
target_dir="$(dirname "$target_file")"
if [ ! -d "$target_dir" ]; then
mkdir -p "$target_dir"
fi
# 파일 복사
if cp "$source_file" "$target_file" 2>/dev/null; then
resource_count=$((resource_count + 1))
fi
done
echo "✅ Copied $resource_count resource files"
echo ""
echo "==============================================="
echo "🎉 Build completed successfully!"
echo "==============================================="
echo "📁 Classes: WebContent/WEB-INF/classes/"
echo "📚 Libraries: WebContent/WEB-INF/lib/"
echo "📝 Logs: logs/"
echo ""
# 빌드 결과 요약
echo "📊 Build Summary:"
if [ -d "WebContent/WEB-INF/classes" ]; then
class_count=$(find WebContent/WEB-INF/classes -name "*.class" | wc -l | tr -d ' ')
echo " - Compiled classes: $class_count"
fi
if [ -d "WebContent/WEB-INF/lib" ]; then
lib_count=$(find WebContent/WEB-INF/lib -name "*.jar" | wc -l | tr -d ' ')
echo " - Library JARs: $lib_count"
fi
echo " - Resource files: $resource_count"
echo ""
echo "🏁 Ready for deployment!"
-101
View File
@@ -1,101 +0,0 @@
@echo off
setlocal enabledelayedexpansion
echo ===============================================
echo Java Application Build for Windows
echo ===============================================
echo.
echo [1] Checking Java environment...
java -version >nul 2>&1
if errorlevel 1 (
echo ERROR: Java not found in PATH
echo Please install Java and add to PATH
exit /b 1
)
javac -version >nul 2>&1
if errorlevel 1 (
echo ERROR: Java compiler not found
echo Please install JDK
exit /b 1
)
echo Java environment OK
echo [2] Cleaning previous build...
if exist "WebContent\WEB-INF\classes" rmdir /s /q "WebContent\WEB-INF\classes"
echo Previous build cleaned
echo [3] Creating directories...
if not exist "WebContent\WEB-INF\classes" mkdir "WebContent\WEB-INF\classes"
if not exist "WebContent\WEB-INF\lib" mkdir "WebContent\WEB-INF\lib"
if not exist "logs" mkdir "logs"
echo Directories created
echo [4] Checking libraries...
set SERVLET_JAR1=WebContent\WEB-INF\lib\javax.servlet-api-4.0.1.jar
set SERVLET_JAR2=WebContent\WEB-INF\lib\servlet-api.jar
if not exist "%SERVLET_JAR1%" if not exist "%SERVLET_JAR2%" (
echo ERROR: Servlet API JAR not found
echo Need: %SERVLET_JAR1% or %SERVLET_JAR2%
exit /b 1
)
echo Libraries OK
echo [5] Setting classpath...
set CLASSPATH=src;WebContent\WEB-INF\lib\*
echo Classpath: %CLASSPATH%
echo [6] Finding Java files...
if exist java_sources.tmp del java_sources.tmp
set java_count=0
for /r src %%f in (*.java) do (
echo %%f >> java_sources.tmp
set /a java_count+=1
)
if %java_count% equ 0 (
echo WARNING: No Java files found
) else (
echo Found %java_count% Java files
)
echo [7] Compiling Java files...
if exist java_sources.tmp (
javac -encoding UTF-8 -source 1.7 -target 1.7 -d WebContent\WEB-INF\classes -cp "%CLASSPATH%" @java_sources.tmp
if errorlevel 1 (
echo ERROR: Compilation failed
del java_sources.tmp
exit /b 1
)
del java_sources.tmp
echo Compilation completed
)
echo [8] Copying resources...
set resource_count=0
for /r src %%f in (*.xml *.properties *.sql) do (
set source_file=%%f
set relative_path=!source_file:%CD%\src\=!
set target_file=WebContent\WEB-INF\classes\!relative_path!
for %%d in ("!target_file!") do (
if not exist "%%~dpd" mkdir "%%~dpd" 2>nul
)
copy "!source_file!" "!target_file!" >nul 2>&1
if not errorlevel 1 set /a resource_count+=1
)
echo Copied %resource_count% resource files
echo.
echo ===============================================
echo Build completed successfully!
echo ===============================================
echo Classes: WebContent\WEB-INF\classes\
echo Libraries: WebContent\WEB-INF\lib\
echo Logs: logs\
echo.
endlocal
-80
View File
@@ -1,80 +0,0 @@
#!/bin/bash
# MAC OS 만 실행
# if [[ "$(uname -s)" != "Darwin" ]]; then
# echo "This script runs on MAC OS only."
# echo "Current OS: $(uname -s)"
# exit 1
# fi
# ----------------------------------------------------------------------
# 기존 빌드 폴더 삭제 및 새로운 빌드 시작
# ----------------------------------------------------------------------
echo "Cleaning up old build artifacts..."
rm -rf WebContent/WEB-INF/classes/*
echo "Building Java application for development..."
# 필요한 디렉토리 생성
mkdir -p WebContent/WEB-INF/classes
mkdir -p WebContent/WEB-INF/lib # lib 폴더 존재 확인
# ----------------------------------------------------------------------
# Servlet API JAR 파일 존재 여부 확인 (단순화된 방식)
# ----------------------------------------------------------------------
SERVLET_API_JAR_PRIMARY_PATH="WebContent/WEB-INF/lib/javax.servlet-api-4.0.1.jar"
SERVLET_API_JAR_ALTERNATIVE_PATH="WebContent/WEB-INF/lib/servlet-api.jar"
if [ ! -f "$SERVLET_API_JAR_PRIMARY_PATH" ] && [ ! -f "$SERVLET_API_JAR_ALTERNATIVE_PATH" ]; then
echo "---------------------------------------------------------------------------------"
echo "ERROR: Servlet API JAR (javax.servlet-api-4.0.1.jar or servlet-api.jar)"
echo " not found in WebContent/WEB-INF/lib/"
echo ""
echo "Please add the appropriate Servlet API JAR for your project."
echo "You can typically find this JAR in a Tomcat distribution's 'lib' folder,"
echo "or download it from a trusted source like Maven Central Repository."
echo ""
echo "Build cannot proceed without it."
echo "---------------------------------------------------------------------------------"
exit 1
else
if [ -f "$SERVLET_API_JAR_PRIMARY_PATH" ]; then
echo "DEBUG: Confirmed Servlet API JAR is present at $SERVLET_API_JAR_PRIMARY_PATH"
elif [ -f "$SERVLET_API_JAR_ALTERNATIVE_PATH" ]; then
echo "DEBUG: Confirmed Servlet API JAR is present at $SERVLET_API_JAR_ALTERNATIVE_PATH"
fi
fi
# ----------------------------------------------------------------------
# 클래스패스 설정 (단순화된 방식)
EFFECTIVE_CLASSPATH="src:WebContent/WEB-INF/lib/*"
echo "DEBUG: Effective classpath for javac: $EFFECTIVE_CLASSPATH"
# src 폴더 내의 모든 .java 파일 컴파일
echo "Compiling Java files for development..."
find src -name "*.java" -print0 | xargs -0 javac -encoding UTF-8 -source 1.7 -target 1.7 -d WebContent/WEB-INF/classes -cp "$EFFECTIVE_CLASSPATH"
if [ $? -ne 0 ]; then
echo "Java compilation failed. Exiting script."
exit 1
fi
echo "Java compilation successful."
# ----------------------------------------------------------------------
# src 폴더 내의 리소스 파일(.xml, .properties 등)을 classes 폴더로 복사 (macOS 호환 방식)
echo "Copying resource files for development..."
find src -type f \( -name "*.xml" -o -name "*.properties" \) | while read -r filepath; do
# 'src/' 접두사를 제거하여 상대 경로 생성
relative_path="${filepath#src/}"
target_file="WebContent/WEB-INF/classes/$relative_path"
# 대상 디렉토리 생성
mkdir -p "$(dirname "$target_file")" || { echo "Error: Failed to create directory $(dirname "$target_file")"; exit 1; }
# 파일 복사
cp "$filepath" "$target_file" || { echo "Error: Failed to copy $filepath to $target_file"; exit 1; }
done
echo "Java application build complete for development."
echo "Build process finished successfully!"
-5
View File
@@ -1,5 +0,0 @@
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_localhost FALSE / FALSE 0 JSESSIONID 99DCC3F6CD4594878206E184A83A6A58
-173
View File
@@ -1,173 +0,0 @@
@echo off
setlocal enabledelayedexpansion
REM ----------------------------------------------------------------------
REM 기존 빌드 폴더 삭제 및 새로운 빌드 시작
REM ----------------------------------------------------------------------
echo Cleaning up old build artifacts...
if exist "WebContent\WEB-INF\classes\*" (
rmdir /s /q "WebContent\WEB-INF\classes"
)
echo Building Java application for development...
REM 필요한 디렉토리 생성
if not exist "WebContent\WEB-INF\classes" mkdir "WebContent\WEB-INF\classes"
if not exist "WebContent\WEB-INF\lib" mkdir "WebContent\WEB-INF\lib"
REM ----------------------------------------------------------------------
REM Servlet API JAR 파일 존재 여부 확인
REM ----------------------------------------------------------------------
set "SERVLET_API_JAR_PRIMARY_PATH=WebContent\WEB-INF\lib\javax.servlet-api-4.0.1.jar"
set "SERVLET_API_JAR_ALTERNATIVE_PATH=WebContent\WEB-INF\lib\servlet-api.jar"
if not exist "%SERVLET_API_JAR_PRIMARY_PATH%" if not exist "%SERVLET_API_JAR_ALTERNATIVE_PATH%" (
echo ---------------------------------------------------------------------------------
echo ERROR: Servlet API JAR (javax.servlet-api-4.0.1.jar or servlet-api.jar^)
echo not found in WebContent\WEB-INF\lib\
echo.
echo Please add the appropriate Servlet API JAR for your project.
echo You can typically find this JAR in a Tomcat distribution's 'lib' folder,
echo or download it from a trusted source like Maven Central Repository.
echo.
echo Build cannot proceed without it.
echo ---------------------------------------------------------------------------------
exit /b 1
) else (
if exist "%SERVLET_API_JAR_PRIMARY_PATH%" (
echo DEBUG: Confirmed Servlet API JAR is present at %SERVLET_API_JAR_PRIMARY_PATH%
) else if exist "%SERVLET_API_JAR_ALTERNATIVE_PATH%" (
echo DEBUG: Confirmed Servlet API JAR is present at %SERVLET_API_JAR_ALTERNATIVE_PATH%
)
)
REM ----------------------------------------------------------------------
REM 클래스패스 설정
set "EFFECTIVE_CLASSPATH=src;WebContent\WEB-INF\lib\*"
echo DEBUG: Effective classpath for javac: %EFFECTIVE_CLASSPATH%
REM src 폴더 내의 모든 .java 파일 컴파일
echo Compiling Java files for development...
REM Java 파일 목록을 임시 파일에 저장
if exist temp_java_files.txt del temp_java_files.txt
for /r src %%f in (*.java) do echo %%f >> temp_java_files.txt
if exist temp_java_files.txt (
javac -encoding UTF-8 -source 1.7 -target 1.7 -d WebContent\WEB-INF\classes -cp "%EFFECTIVE_CLASSPATH%" @temp_java_files.txt
if !errorlevel! neq 0 (
echo Java compilation failed. Exiting script.
del temp_java_files.txt
exit /b 1
)
del temp_java_files.txt
)
echo Java compilation successful.
REM ----------------------------------------------------------------------
REM src 폴더 내의 리소스 파일(.xml, .properties 등)을 classes 폴더로 복사
echo Copying resource files for development...
for /r src %%f in (*.xml *.properties) do (
set "filepath=%%f"
REM src\ 부분을 제거하여 상대 경로 생성
set "relative_path=%%f"
call set "relative_path=%%relative_path:*src\=%%"
set "target_file=WebContent\WEB-INF\classes\!relative_path!"
REM 대상 디렉토리 생성
for %%d in ("!target_file!") do (
if not exist "%%~dpd" mkdir "%%~dpd"
)
REM 파일 복사
copy "!filepath!" "!target_file!" >nul
if !errorlevel! neq 0 (
echo Error: Failed to copy !filepath! to !target_file!
exit /b 1
)
)
echo Java application build complete for development.
REM ----------------------------------------------------------------------
REM Git 변경사항 커밋 및 푸시
REM ----------------------------------------------------------------------
git add .
git commit -am "auto commit"
REM 현재 브랜치 확인
for /f "tokens=*" %%i in ('git branch --show-current') do set "current_branch=%%i"
git push origin %current_branch%
REM 마스터 브랜치와 병합 여부 확인
echo You are currently on branch: %current_branch%
set /p "proceed_merge=Would you like to merge the current branch with main? (Y/N) [Y]: "
if "%proceed_merge%"=="" set "proceed_merge=Y"
if /i "%proceed_merge%"=="Y" (
REM 마스터 브랜치로 전환 및 업데이트
git checkout main
git pull origin main
REM 현재 브랜치를 마스터에 병합
git merge --no-edit %current_branch%
REM 병합 결과 푸시
git push origin main
REM 원래 브랜치로 돌아가기
git checkout %current_branch%
)
REM 새로운 브랜치 생성
REM 현재 날짜를 YYYYMMDD 형식으로 가져오기
for /f "tokens=2 delims==" %%i in ('wmic OS Get localdatetime /value') do set "dt=%%i"
set "current_date=%dt:~0,8%"
REM 브랜치 이름에서 날짜 부분 추출
set "branch_date=%current_branch:~1,8%"
REM 현재 날짜와 브랜치 날짜가 같으면 뒤의 2자리 숫자를 증가시킴
if "%branch_date%"=="%current_date%" (
set "branch_number=%current_branch:~9,2%"
set /a "branch_number=branch_number+1"
) else (
set "branch_number=1"
)
REM 사용 가능한 브랜치 이름 찾기
:find_branch
if %branch_number% lss 10 (
set "formatted_number=0%branch_number%"
) else (
set "formatted_number=%branch_number%"
)
set "new_branch=V%current_date%%formatted_number%"
REM 로컬과 원격에 해당 이름의 브랜치가 존재하는지 확인
git show-ref --quiet refs/heads/%new_branch% >nul 2>&1
if !errorlevel! equ 0 goto increment_branch
git ls-remote --exit-code --heads origin %new_branch% >nul 2>&1
if !errorlevel! equ 0 goto increment_branch
goto create_branch
:increment_branch
set /a "branch_number=branch_number+1"
goto find_branch
:create_branch
REM 새로운 브랜치 생성
git checkout -b %new_branch%
REM 새로운 브랜치 푸시
git push origin %new_branch%
REM 변경 사항 확인
git status
endlocal
-176
View File
@@ -1,176 +0,0 @@
#!/bin/bash
# MAC OS 만 실행
# if [[ "$(uname -s)" != "Darwin" ]]; then
# echo "This script runs on MAC OS only."
# echo "Current OS: $(uname -s)"
# exit 1
# fi
# ----------------------------------------------------------------------
# 기존 빌드 폴더 삭제 및 새로운 빌드 시작
# ----------------------------------------------------------------------
echo "Cleaning up old build artifacts..."
rm -rf WebContent/WEB-INF/classes/*
echo "Building Java application for development..."
# 필요한 디렉토리 생성
mkdir -p WebContent/WEB-INF/classes
mkdir -p WebContent/WEB-INF/lib # lib 폴더 존재 확인
# ----------------------------------------------------------------------
# Servlet API JAR 파일 존재 여부 확인 (단순화된 방식)
# ----------------------------------------------------------------------
SERVLET_API_JAR_PRIMARY_PATH="WebContent/WEB-INF/lib/javax.servlet-api-4.0.1.jar"
SERVLET_API_JAR_ALTERNATIVE_PATH="WebContent/WEB-INF/lib/servlet-api.jar"
if [ ! -f "$SERVLET_API_JAR_PRIMARY_PATH" ] && [ ! -f "$SERVLET_API_JAR_ALTERNATIVE_PATH" ]; then
echo "---------------------------------------------------------------------------------"
echo "ERROR: Servlet API JAR (javax.servlet-api-4.0.1.jar or servlet-api.jar)"
echo " not found in WebContent/WEB-INF/lib/"
echo ""
echo "Please add the appropriate Servlet API JAR for your project."
echo "You can typically find this JAR in a Tomcat distribution's 'lib' folder,"
echo "or download it from a trusted source like Maven Central Repository."
echo ""
echo "Build cannot proceed without it."
echo "---------------------------------------------------------------------------------"
exit 1
else
if [ -f "$SERVLET_API_JAR_PRIMARY_PATH" ]; then
echo "DEBUG: Confirmed Servlet API JAR is present at $SERVLET_API_JAR_PRIMARY_PATH"
elif [ -f "$SERVLET_API_JAR_ALTERNATIVE_PATH" ]; then
echo "DEBUG: Confirmed Servlet API JAR is present at $SERVLET_API_JAR_ALTERNATIVE_PATH"
fi
fi
# ----------------------------------------------------------------------
# 클래스패스 설정 (단순화된 방식)
EFFECTIVE_CLASSPATH="src:WebContent/WEB-INF/lib/*"
echo "DEBUG: Effective classpath for javac: $EFFECTIVE_CLASSPATH"
# src 폴더 내의 모든 .java 파일 컴파일
echo "Compiling Java files for development..."
find src -name "*.java" -print0 | xargs -0 javac -encoding UTF-8 -source 1.7 -target 1.7 -d WebContent/WEB-INF/classes -cp "$EFFECTIVE_CLASSPATH" -Xlint:-options -Xlint:-deprecation -Xlint:-unchecked
if [ $? -ne 0 ]; then
echo "=================================="
echo "ERROR: Java compilation failed!"
echo "=================================="
echo "Please check:"
echo "1. Java version (should be 1.7 or compatible)"
echo "2. All required JAR files in WebContent/WEB-INF/lib/"
echo "3. Source code syntax errors"
exit 1
fi
echo "Java compilation successful."
# 컴파일 결과 요약 출력
COMPILED_CLASSES=$(find WebContent/WEB-INF/classes -name "*.class" | wc -l)
echo "INFO: Compiled $COMPILED_CLASSES Java class files."
# 컴파일 검증 - 클래스 파일이 생성되었는지 확인
if [ $COMPILED_CLASSES -eq 0 ]; then
echo "=================================="
echo "ERROR: No class files were generated!"
echo "=================================="
echo "Build failed - no Java classes were compiled."
echo "Check if there are .java files in the src directory."
exit 1
fi
# ----------------------------------------------------------------------
# src 폴더 내의 리소스 파일(.xml, .properties 등)을 classes 폴더로 복사 (macOS 호환 방식)
echo "Copying resource files for development..."
find src -type f \( -name "*.xml" -o -name "*.properties" \) | while read -r filepath; do
# 'src/' 접두사를 제거하여 상대 경로 생성
relative_path="${filepath#src/}"
target_file="WebContent/WEB-INF/classes/$relative_path"
# 대상 디렉토리 생성
mkdir -p "$(dirname "$target_file")" || { echo "Error: Failed to create directory $(dirname "$target_file")"; exit 1; }
# 파일 복사
cp "$filepath" "$target_file" || { echo "Error: Failed to copy $filepath to $target_file"; exit 1; }
done
# 파이프라인의 마지막 명령어의 종료 코드를 확인하기 위해 추가적인 검사가 필요할 수 있으나,
# while 루프 내에서 오류 발생 시 exit 하므로, 이 지점에 도달하면 성공으로 간주합니다.
# 만약 find가 아무 파일도 찾지 못해도 오류가 아니어야 하므로 $? 검사는 주의해야 합니다.
# 리소스 파일 복사 결과 요약 출력
COPIED_XML=$(find WebContent/WEB-INF/classes -name "*.xml" | wc -l)
COPIED_PROPERTIES=$(find WebContent/WEB-INF/classes -name "*.properties" | wc -l)
echo "INFO: Copied $COPIED_XML XML files and $COPIED_PROPERTIES properties files."
echo "Java application build complete for development."
echo "=========================================="
echo "BUILD SUMMARY:"
echo "- Java classes: $COMPILED_CLASSES"
echo "- XML files: $COPIED_XML"
echo "- Properties files: $COPIED_PROPERTIES"
echo "=========================================="
# ----------------------------------------------------------------------
# 빌드 종료
# ----------------------------------------------------------------------
# Git 변경사항 커밋 및 푸시
git add .
git commit -am "auto commit"
current_branch=$(git branch --show-current)
git push origin $current_branch
# 마스터 브랜치와 병합 여부 확인
echo "You are currently on branch: $current_branch"
echo "Would you like to merge the current branch with main? (Y/N) [Y]"
read proceed_merge
proceed_merge=${proceed_merge:-Y}
if [ "$proceed_merge" == "Y" ] || [ "$proceed_merge" == "y" ]; then
# 마스터 브랜치로 전환 및 업데이트
git checkout main
git pull origin main
# 현재 브랜치를 마스터에 병합
git merge --no-edit $current_branch
# 병합 결과 푸시
git push origin main
# 원래 브랜치로 돌아가기
git checkout $current_branch
fi
# 새로운 브랜치 생성
# 현재 날짜를 YYYYMMDD 형식으로 가져오기
current_date=$(date +'%Y%m%d')
# 브랜치 이름에서 날짜 부분 추출
branch_date=${current_branch:1:8}
# 현재 날짜와 브랜치 날짜가 같으면 뒤의 2자리 숫자를 증가시킴
if [ "$branch_date" == "$current_date" ]; then
# 브랜치 이름에서 뒤의 2자리 숫자 추출
branch_number=${current_branch:9:2}
# 숫자를 10진수로 변환하고 1 증가시킴
branch_number=$((10#$branch_number + 1))
else
# 날짜가 다르면 01부터 시작
branch_number=1
fi
# 사용 가능한 브랜치 이름 찾기
while true; do
# 2자리 숫자로 포맷팅
formatted_number=$(printf "%02d" $branch_number)
new_branch="V${current_date}${formatted_number}"
# 로컬과 원격에 해당 이름의 브랜치가 존재하는지 확인
if ! git show-ref --quiet refs/heads/$new_branch && \
! git ls-remote --exit-code --heads origin $new_branch > /dev/null 2>&1; then
break
fi
# 존재한다면 숫자 증가
branch_number=$((branch_number + 1))
done
# 새로운 브랜치 생성
git checkout -b $new_branch
# 새로운 브랜치 푸시 (원격 브랜치로 푸시하려면 git push origin $new_branch 실행)
git push origin $new_branch
# 변경 사항 확인
git status
# .env-dev 파일을 .env로 복사하여 원래 상태로 복원
# docker-compose -f docker-compose-dev.yml up -d --build
-44
View File
@@ -1,44 +0,0 @@
version: '3.8'
services:
momo-erp:
build:
context: .
dockerfile: Dockerfile.dev
container_name: momo-erp-debug
ports:
- "9090:8080"
- "5005:5005" # 디버깅 포트
env_file:
- .env
environment:
CATALINA_OPTS: >-
-DDB_URL=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
-DDB_USERNAME=${DB_USERNAME}
-DDB_PASSWORD=${DB_PASSWORD}
-Xdebug
-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=0.0.0.0:5005
-Djava.security.egd=file:/dev/./urandom
-Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties
-Dorg.apache.catalina.startup.EXIT_ON_INIT_FAILURE=true
-Dlogging.level.org.springframework=INFO
-Dlogging.level.org.apache=WARN
-Dlogging.level.com.pms=DEBUG
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
volumes:
- ./WebContent/WEB-INF/classes:/usr/local/tomcat/webapps/ROOT/WEB-INF/classes
- ./WebContent/WEB-INF/view:/usr/local/tomcat/webapps/ROOT/WEB-INF/view
- ./WebContent/css:/usr/local/tomcat/webapps/ROOT/css
- ./WebContent/js:/usr/local/tomcat/webapps/ROOT/js
- ./WebContent/images:/usr/local/tomcat/webapps/ROOT/images
- momo-erp-project_data:/data_storage
- momo-erp-app_data:/path/inside/container
restart: unless-stopped
volumes:
momo-erp-project_data:
momo-erp-app_data:
-25
View File
@@ -1,25 +0,0 @@
version: '3.8'
services:
momo-erp:
build:
context: .
dockerfile: dockerfilelocal.dev
container_name: momo-erp-dev
ports:
- "3643:8080"
env_file:
- .env
environment:
CATALINA_OPTS: >-
-DDB_URL=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
-DDB_USERNAME=${DB_USERNAME}
-DDB_PASSWORD=${DB_PASSWORD}
volumes:
- momo-erp-project_data:/data_storage
- momo-erp-app_data:/path/inside/container
restart: unless-stopped
volumes:
momo-erp-project_data:
momo-erp-app_data:
-35
View File
@@ -1,35 +0,0 @@
services:
momo-erp:
build:
context: .
dockerfile: Dockerfile.win
platforms:
- linux/amd64
container_name: momo-erp
ports:
- "7777:8080"
env_file:
- .env
environment:
- CATALINA_OPTS=-DDB_URL=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME} -DDB_USERNAME=${DB_USERNAME} -DDB_PASSWORD=${DB_PASSWORD} -Xms512m -Xmx1024m
- TZ=Asia/Seoul
- APP_ENV=development
- LOG_LEVEL=INFO
volumes:
- momo-erp-project:/data_storage
- momo-erp-app:/app_data
- ./logs:/usr/local/tomcat/logs
- ./WebContent:/usr/local/tomcat/webapps/ROOT
restart: unless-stopped
networks:
- momo-erp-network
volumes:
momo-erp-project:
driver: local
momo-erp-app:
driver: local
networks:
momo-erp-network:
driver: bridge
-23
View File
@@ -1,23 +0,0 @@
FROM localhost:8787/tomcat:7.0.94-jre7-alpine.linux AS Development
# Remove default webapps
RUN rm -rf /usr/local/tomcat/webapps/*
# Copy web application content (compiled classes and web resources)
COPY WebContent /usr/local/tomcat/webapps/ROOT
COPY src /usr/local/tomcat/webapps/ROOT/WEB-INF/src
# Copy custom Tomcat context configuration for JNDI
COPY ./tomcat-conf/context.xml /usr/local/tomcat/conf/context.xml
# Configure Tomcat Connector for UTF-8 URI encoding
RUN sed -i 's/<Connector port="8080"/<Connector port="8080" URIEncoding="UTF-8"/g' /usr/local/tomcat/conf/server.xml
# Copy database driver if needed (PostgreSQL driver is already in WEB-INF/lib)
# COPY path/to/postgresql-driver.jar /usr/local/tomcat/lib/
# Expose Tomcat port
EXPOSE 8080
# Start Tomcat
CMD ["catalina.sh", "run"]
-26
View File
@@ -1,26 +0,0 @@
# PLM ILSHIN 개발환경 설정
# 애플리케이션 환경
NODE_ENV=development
# 데이터베이스 설정
DB_URL=jdbc:postgresql://211.115.91.141:11140/fito
DB_USERNAME=postgres
DB_PASSWORD=intops0909!!
# PostgreSQL 환경 변수 (내부 DB 사용 시)
POSTGRES_DB=fito
POSTGRES_USER=postgres
POSTGRES_PASSWORD=intops0909!!
# 애플리케이션 포트
APP_PORT=8090
# JVM 옵션
JAVA_OPTS=-Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m
# 로그 레벨
LOG_LEVEL=DEBUG
# 개발 모드 플래그
DEBUG=true
-29
View File
@@ -1,29 +0,0 @@
# PLM ILSHIN 운영환경 설정
# 애플리케이션 환경
NODE_ENV=production
# 데이터베이스 설정
DB_URL=jdbc:postgresql://211.115.91.141:11140/fito
DB_USERNAME=postgres
DB_PASSWORD=intops0909!!
# PostgreSQL 환경 변수
POSTGRES_DB=fito
POSTGRES_USER=postgres
POSTGRES_PASSWORD=intops0909!!
# JVM 옵션 (운영환경용)
JAVA_OPTS=-Xms1024m -Xmx2048m -XX:PermSize=512m -XX:MaxPermSize=1024m
# 로그 레벨
LOG_LEVEL=INFO
# 개발 모드 플래그
DEBUG=false
# SSL 설정
SSL_ENABLED=true
# 도메인 설정
DOMAIN=fito.wace.me
-5
View File
@@ -1,5 +0,0 @@
* 4a63e73 (origin/main, origin/V2025080502, origin/V2025080501, origin/HEAD, main, V2025080501) auto commit
* 4dd7d21 auto commit
* aac2d92 업데이트된 변경사항 커밋
* 77a3690 영업및 영업회의 등록 수정정
* c68ff72 auto commit
-5
View File
@@ -1,5 +0,0 @@
V2025080501
V2025080502
* V2025080601
V2025080801
main
-21
View File
@@ -1,21 +0,0 @@
#!/bin/bash
# macOS 전용 빠른 재빌드 스크립트
echo "🔄 Quick rebuild starting..."
# Java 컴파일
echo "⚙️ Compiling Java files..."
export PATH="/opt/homebrew/opt/openjdk@11/bin:$PATH"
./build-mac.sh
if [ $? -ne 0 ]; then
echo "❌ Build failed. Exiting."
exit 1
fi
# Docker 컨테이너 재시작 (빌드 캐시 활용)
echo "🐳 Rebuilding Docker container..."
docker-compose -f docker-compose.dev.yml up --build -d
echo "✅ Quick rebuild completed!"
echo "🌐 Application available at: http://localhost:9090"
-36
View File
@@ -1,36 +0,0 @@
#!/bin/bash
# JSP 파일 빠른 업데이트 스크립트
# 사용법: ./quick-update-jsp.sh [JSP파일경로]
if [ -z "$1" ]; then
echo "❌ 사용법: ./quick-update-jsp.sh [JSP파일경로]"
echo "예시: ./quick-update-jsp.sh WebContent/WEB-INF/view/salesMng/salesBomReportFormPopup.jsp"
exit 1
fi
JSP_FILE="$1"
CONTAINER_NAME="plm-ilshin-dev"
if [ ! -f "$JSP_FILE" ]; then
echo "❌ 파일을 찾을 수 없습니다: $JSP_FILE"
exit 1
fi
# WebContent 이후 경로 추출
RELATIVE_PATH="${JSP_FILE#WebContent/}"
echo "📝 JSP 파일 업데이트 중..."
echo " 로컬: $JSP_FILE"
echo " 컨테이너: /usr/local/tomcat/webapps/ROOT/$RELATIVE_PATH"
# 컨테이너에 파일 복사
docker cp "$JSP_FILE" "$CONTAINER_NAME:/usr/local/tomcat/webapps/ROOT/$RELATIVE_PATH"
if [ $? -eq 0 ]; then
echo "✅ 업데이트 완료! 브라우저 새로고침(Cmd+Shift+R) 하세요!"
else
echo "❌ 업데이트 실패!"
exit 1
fi
-40
View File
@@ -1,40 +0,0 @@
@echo off
echo Starting PLM Windows...
echo [1] Building application...
call build-windows.bat
if %errorlevel% neq 0 (
echo Build failed! Cannot proceed.
pause
exit /b 1
)
echo [2] Stopping existing containers...
docker-compose -f docker-compose.win.yml down 2>nul
echo [3] Starting PLM containers...
docker-compose -f docker-compose.win.yml up --build --force-recreate -d
if %errorlevel% equ 0 (
echo.
echo PLM started successfully!
echo Web: http://localhost:7777
echo.
@REM set /p "run_git=Would you like to run git operations? (Y/N) [N]: "
@REM if "%run_git%"=="" set "run_git=N"
@REM if /i "%run_git%"=="Y" (
@REM echo Running git operations...
@REM call dev_git_only.bat
@REM )
timeout /t 5 /nobreak >nul
start http://localhost:7777
) else (
echo.
echo PLM start failed!
echo Check: docker-compose -f docker-compose.win.yml logs
pause
)
+123
View File
@@ -0,0 +1,123 @@
// 운영 E2E: 가입(또는 기존 로그인) → 발주 → 관리자 승인 → 메일
// 모든 거래처 비밀번호: test1234 (AES 인코딩 일치)
// 관리자: plm_admin / qlalfqjsgh11 (FITO 마스터)
import pg from "pg";
const BASE = process.env.E2E_BASE || "https://momo.junggomoa.com";
const DB_URL = "postgresql://momo_app:qlalfqjsgh11@183.99.177.40:5432/distribution";
const log = (...a) => console.log("[e2e]", ...a);
const fail = (m) => { console.error("[e2e] ✖", m); process.exit(1); };
const apiClient = (jar) => async (path, init = {}) => {
const res = await fetch(`${BASE}${path}`, {
...init,
headers: {
"Content-Type": "application/json",
...(jar.value ? { Cookie: jar.value } : {}),
...(init.headers ?? {}),
},
redirect: "manual",
});
const sc = res.headers.getSetCookie?.() || [];
for (const c of sc) {
const kv = c.split(";")[0];
const k = kv.split("=")[0];
jar.value = jar.value
? jar.value.split("; ").filter((p) => !p.startsWith(k + "=")).concat(kv).join("; ")
: kv;
}
const text = await res.text();
let json;
try { json = JSON.parse(text); } catch { json = { raw: text.slice(0, 200) }; }
return { status: res.status, body: json };
};
// 1. 헬스체크
log("0. 헬스체크");
const h = await fetch(`${BASE}/`);
log(` ${h.status} ${BASE}/`);
// 2. DB 시드 검증
const db = new pg.Client({ connectionString: DB_URL });
await db.connect();
const itemRows = await db.query(`SELECT objid, item_name FROM momo_items WHERE item_code LIKE 'SAMP-%' ORDER BY item_code LIMIT 5`);
log(` 샘플 품목 ${itemRows.rowCount}개 확인`);
// 3. 거래처 로그인 (chpark@wace.me / test1234)
log("1. 거래처 로그인 — chpark@wace.me");
const userJar = { value: "" };
const userApi = apiClient(userJar);
const login = await userApi("/api/auth/login", {
method: "POST", body: JSON.stringify({ userId: "chpark@wace.me", password: "test1234" }),
});
if (!login.body.success) fail(`거래처 로그인 실패: ${JSON.stringify(login.body)}`);
log(` ✔ 로그인 성공, redirectTo=${login.body.redirectTo}`);
// 4. 품목 조회
log("2. 품목 검색");
const items = await userApi("/api/m/items/list", {
method: "POST", body: JSON.stringify({ keyword: "SAMP" }),
});
const visible = (items.body.RESULTLIST || []).filter((r) => r.ITEM_CODE?.startsWith("SAMP-"));
if (visible.length === 0) fail(`품목 조회 실패: ${JSON.stringify(items.body)}`);
log(`${visible.length}개 품목 노출 (재고 ${visible[0].STOCK_QTY})`);
// 5. 출고 요청
log("3. 출고 요청");
const order = await userApi("/api/m/orders/save", {
method: "POST",
body: JSON.stringify({
lines: [
{ itemObjid: visible[0].OBJID, qty: 5 },
{ itemObjid: visible[1]?.OBJID, qty: 3 },
].filter((l) => l.itemObjid),
memo: "최종 E2E 테스트",
}),
});
if (!order.body.success) fail(`발주 실패: ${JSON.stringify(order.body)}`);
log(` ✔ 발주번호 ${order.body.orderNo}`);
// 6. 관리자 로그인
log("4. 관리자 로그인 (plm_admin)");
const adminJar = { value: "" };
const adminApi = apiClient(adminJar);
const adminLogin = await adminApi("/api/auth/login", {
method: "POST", body: JSON.stringify({ userId: "plm_admin", password: "qlalfqjsgh11" }),
});
if (!adminLogin.body.success) fail(`관리자 로그인 실패: ${JSON.stringify(adminLogin.body)}`);
log(` ✔ 관리자 세션`);
// 7. 출고 관리 목록 조회
log("5. 출고 목록 조회 (관리자)");
const orderList = await adminApi("/api/m/orders/list", {
method: "POST", body: JSON.stringify({ status: "REQUESTED" }),
});
log(` 요청 상태 발주: ${orderList.body.RESULTLIST?.length ?? 0}`);
// 8. 발주 승인 + 메일 발송
log("6. 발주 승인 (메일 자동 발송)");
const approve = await adminApi("/api/m/orders/approve", {
method: "POST", body: JSON.stringify({ objid: order.body.objId }),
});
if (!approve.body.success) fail(`승인 실패: ${JSON.stringify(approve.body)}`);
log(` ✔ 승인 완료. mailSent=${approve.body.mailSent}, error=${approve.body.mailError ?? "(none)"}`);
// 9. 후속 검증
const finalRow = await db.query(
`SELECT order_no, status, total_amount, total_taxfree, total_taxable
FROM momo_orders WHERE objid = $1`,
[order.body.objId]
);
log(` 주문 ${finalRow.rows[0].order_no}: status=${finalRow.rows[0].status}, total=${finalRow.rows[0].total_amount}`);
const mailRow = await db.query(
`SELECT to_email, subject, status FROM momo_mail_logs WHERE ref_objid = $1 ORDER BY regdate DESC LIMIT 1`,
[order.body.objId]
);
if (mailRow.rowCount > 0) {
const m = mailRow.rows[0];
log(` 메일 → ${m.to_email}, status=${m.status}, subject=${m.subject}`);
}
await db.end();
log("✔ E2E 전체 통과");
-192
View File
@@ -1,192 +0,0 @@
#!/bin/bash
# ==============================================================================
# PLM 프로젝트 환경 설정 스크립트
# ==============================================================================
echo "================================================================"
echo "PLM 프로젝트 환경 설정을 시작합니다..."
echo "================================================================"
# ------------------------------------------------------------------------------
# 1. Git 설정
# ------------------------------------------------------------------------------
echo "🔧 Git 설정 중..."
# Git 사용자 정보 설정 (이미 설정되어 있으면 건너뜀)
if [ -z "$(git config --global user.name)" ]; then
echo "Git 사용자 이름을 설정합니다..."
git config --global user.name "PLM Developer"
fi
if [ -z "$(git config --global user.email)" ]; then
echo "Git 이메일을 설정합니다..."
git config --global user.email "developer@plm-ilshin.local"
fi
# Git 기본 설정
git config --global init.defaultBranch main
git config --global pull.rebase false
git config --global core.autocrlf input
git config --global core.safecrlf false
echo "✅ Git 설정 완료"
# ------------------------------------------------------------------------------
# 2. 파일 소유권 설정
# ------------------------------------------------------------------------------
echo "📁 파일 소유권 설정 중..."
# 전체 프로젝트 소유권을 현재 사용자로 변경
sudo chown -R $USER:$USER .
# 특히 중요한 디렉토리들의 소유권 확인
sudo chown -R $USER:$USER WebContent/
sudo chown -R $USER:$USER src/
sudo chown -R $USER:$USER db/
echo "✅ 파일 소유권 설정 완료"
# ------------------------------------------------------------------------------
# 3. 디렉토리 권한 설정
# ------------------------------------------------------------------------------
echo "🔐 디렉토리 권한 설정 중..."
# 주요 디렉토리 권한 설정
chmod 755 .
chmod -R 755 WebContent/
chmod -R 755 src/
chmod -R 755 db/
# 스크립트 파일들 실행 권한 부여
find . -name "*.sh" -type f -exec chmod +x {} \;
# classes 디렉토리가 없으면 생성하고 권한 설정
mkdir -p WebContent/WEB-INF/classes
chmod 755 WebContent/WEB-INF/classes
# lib 디렉토리 권한 설정
if [ -d "WebContent/WEB-INF/lib" ]; then
chmod 755 WebContent/WEB-INF/lib
fi
echo "✅ 디렉토리 권한 설정 완료"
# ------------------------------------------------------------------------------
# 4. JSP 파일 권한 설정
# ------------------------------------------------------------------------------
echo "📄 JSP 파일 권한 설정 중..."
# view 디렉토리의 모든 JSP 파일 권한 설정
if [ -d "WebContent/WEB-INF/view" ]; then
find WebContent/WEB-INF/view -name "*.jsp" -type f -exec chmod 644 {} \;
find WebContent/WEB-INF/view -type d -exec chmod 755 {} \;
fi
echo "✅ JSP 파일 권한 설정 완료"
# ------------------------------------------------------------------------------
# 5. 빌드 환경 정리
# ------------------------------------------------------------------------------
echo "🧹 빌드 환경 정리 중..."
# 기존 클래스 파일 삭제 (권한 문제 없이)
if [ -d "WebContent/WEB-INF/classes" ]; then
rm -rf WebContent/WEB-INF/classes/*
fi
# 필요한 디렉토리 다시 생성
mkdir -p WebContent/WEB-INF/classes
mkdir -p WebContent/WEB-INF/lib
echo "✅ 빌드 환경 정리 완료"
# ------------------------------------------------------------------------------
# 6. Docker 권한 설정 (Docker가 설치되어 있는 경우)
# ------------------------------------------------------------------------------
if command -v docker &> /dev/null; then
echo "🐳 Docker 권한 설정 중..."
# Docker 그룹에 현재 사용자 추가 (이미 추가되어 있으면 무시됨)
if ! groups $USER | grep -q docker; then
sudo usermod -aG docker $USER
echo "⚠️ Docker 그룹에 추가되었습니다. 변경사항 적용을 위해 로그아웃 후 다시 로그인하세요."
fi
echo "✅ Docker 권한 설정 완료"
fi
# ------------------------------------------------------------------------------
# 7. Tomcat 설정 파일 권한
# ------------------------------------------------------------------------------
echo "☕ Tomcat 설정 권한 설정 중..."
if [ -d "tomcat-conf" ]; then
chmod -R 644 tomcat-conf/*
chmod 755 tomcat-conf
fi
echo "✅ Tomcat 설정 권한 설정 완료"
# ------------------------------------------------------------------------------
# 8. 환경 변수 및 alias 설정
# ------------------------------------------------------------------------------
echo "⚙️ 환경 설정 중..."
# .bashrc에 PLM 프로젝트 관련 alias 추가 (중복 방지)
if ! grep -q "# PLM Project Aliases" ~/.bashrc; then
cat >> ~/.bashrc << 'EOF'
# PLM Project Aliases
alias plm-setup='cd ~/plm-ilshin && ./setup.sh'
alias plm-build='cd ~/plm-ilshin && ./dev_git_only.sh'
alias plm-clean='cd ~/plm-ilshin && rm -rf WebContent/WEB-INF/classes/* && echo "Build artifacts cleaned"'
alias plm-logs='cd ~/plm-ilshin && docker-compose logs -f'
alias plm-restart='cd ~/plm-ilshin && docker-compose restart'
EOF
echo "✅ PLM 프로젝트 alias가 ~/.bashrc에 추가되었습니다."
fi
echo "✅ 환경 설정 완료"
# ------------------------------------------------------------------------------
# 9. 설정 검증
# ------------------------------------------------------------------------------
echo "🔍 설정 검증 중..."
# 주요 파일들의 소유권 확인
echo "주요 파일 소유권 확인:"
ls -la WebContent/WEB-INF/view/contractMgmt/ | head -5
echo ""
# Git 설정 확인
echo "Git 설정 확인:"
echo "사용자: $(git config --global user.name)"
echo "이메일: $(git config --global user.email)"
echo ""
# 디렉토리 권한 확인
echo "주요 디렉토리 권한 확인:"
ls -ld WebContent/ src/ WebContent/WEB-INF/classes/
echo ""
echo "✅ 설정 검증 완료"
# ------------------------------------------------------------------------------
# 완료 메시지
# ------------------------------------------------------------------------------
echo "================================================================"
echo "🎉 PLM 프로젝트 환경 설정이 완료되었습니다!"
echo "================================================================"
echo ""
echo "📌 추가된 명령어들:"
echo " plm-setup : 이 설정 스크립트 재실행"
echo " plm-build : 프로젝트 빌드 및 Git 작업"
echo " plm-clean : 빌드 산출물 정리"
echo " plm-logs : Docker 로그 확인"
echo " plm-restart : Docker 컨테이너 재시작"
echo ""
echo "💡 터미널을 재시작하거나 'source ~/.bashrc'를 실행하여"
echo " 새로운 alias를 사용할 수 있습니다."
echo ""
echo "🚀 이제 개발을 시작할 수 있습니다!"
echo "================================================================"
-138
View File
@@ -1,138 +0,0 @@
#!/bin/bash
# 스마트 로그 뷰어 (pretty-logs + clean-logs 통합)
echo -e "\033[1;36m🎨 Smart Log Viewer\033[0m"
echo -e "\033[1;36m===================\033[0m"
# 컨테이너 확인
CONTAINER_NAME=$(docker ps --format "table {{.Names}}" | grep plm-ilshin | head -1)
if [ -z "$CONTAINER_NAME" ]; then
echo -e "\033[1;31m❌ No PLM container running\033[0m"
echo -e "\033[1;33m💡 Start with: ./start-debug.sh\033[0m"
exit 1
fi
echo -e "\033[1;32m🐳 Container: $CONTAINER_NAME\033[0m"
echo -e "\033[1;35m⏰ Started: $(date)\033[0m"
echo ""
# 메뉴 표시
echo -e "\033[1;36m🔍 Choose log view:\033[0m"
echo -e "\033[1;31m 1) 🔴 Errors & Exceptions only\033[0m"
echo -e "\033[1;33m 2) 🟡 Warnings & Errors\033[0m"
echo -e "\033[1;32m 3) 📱 Application logs (clean, auto-clear)\033[0m"
echo -e "\033[1;34m 4) 🗃️ SQL queries only\033[0m"
echo -e "\033[1;35m 5) 🎯 Custom keyword search\033[0m"
echo -e "\033[1;37m 6) 📋 Recent summary (last 20)\033[0m"
echo -e "\033[1;36m 7) 🌈 All logs (with auto-clear)\033[0m"
echo ""
read -p "$(echo -e '\033[1;36mChoose option (1-7): \033[0m')" choice
# 자동 클리어 기능이 있는 로그 포맷팅 함수
format_log_with_autoclear() {
local log_count=0
local max_logs=50
while IFS= read -r line; do
# 자동 클리어 (옵션 3, 7에서만)
if [[ "$1" == "autoclear" ]] && [ $log_count -ge $max_logs ]; then
clear
echo -e "\033[1;36m🎨 Smart Log Viewer (Auto-cleared)\033[0m"
echo -e "\033[1;32m🐳 $CONTAINER_NAME\033[0m"
echo -e "\033[0;90m(Press Ctrl+C to stop)\033[0m"
echo ""
log_count=0
fi
# 타임스탬프 추출
if [[ $line =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2} ]]; then
timestamp=$(echo "$line" | cut -d' ' -f1 | cut -dT -f2 | cut -d. -f1)
content=$(echo "$line" | cut -d' ' -f2-)
else
timestamp=$(date '+%H:%M:%S')
content="$line"
fi
# 로그 레벨에 따른 컬러링
if [[ $content == *"ERROR"* ]] || [[ $content == *"Exception"* ]] || [[ $content == *"Failed"* ]]; then
echo -e "\033[1;31m[$timestamp] 🔴 $content\033[0m"
elif [[ $content == *"WARN"* ]] || [[ $content == *"Warning"* ]]; then
echo -e "\033[1;33m[$timestamp] 🟡 $content\033[0m"
elif [[ $content == *"INFO"* ]] || [[ $content == *"Started"* ]] || [[ $content == *"Completed"* ]]; then
echo -e "\033[1;32m[$timestamp] 📗 $content\033[0m"
elif [[ $content == *"DEBUG"* ]]; then
echo -e "\033[1;36m[$timestamp] 🔍 $content\033[0m"
elif [[ $content == *"SELECT"* ]] || [[ $content == *"INSERT"* ]] || [[ $content == *"UPDATE"* ]] || [[ $content == *"DELETE"* ]]; then
echo -e "\033[1;35m[$timestamp] 🗃️ $content\033[0m"
else
echo -e "\033[0;37m[$timestamp] 📄 $content\033[0m"
fi
log_count=$((log_count + 1))
done
}
# 일반 로그 포맷팅 함수 (자동 클리어 없음)
format_log() {
format_log_with_autoclear "normal"
}
# 선택에 따른 실행
case $choice in
1)
clear
echo -e "\033[1;31m🔴 Showing ERRORS & EXCEPTIONS...\033[0m"
echo -e "\033[0;90m(Press Ctrl+C to stop)\033[0m"
echo ""
docker logs -f --timestamps "$CONTAINER_NAME" 2>&1 | grep -i -E "(error|exception|failed|fatal)" | format_log
;;
2)
clear
echo -e "\033[1;33m🟡 Showing WARNINGS & ERRORS...\033[0m"
echo -e "\033[0;90m(Press Ctrl+C to stop)\033[0m"
echo ""
docker logs -f --timestamps "$CONTAINER_NAME" 2>&1 | grep -i -E "(error|exception|failed|warn|fatal)" | format_log
;;
3)
clear
echo -e "\033[1;32m📱 Showing APPLICATION logs (clean, auto-clear)...\033[0m"
echo -e "\033[0;90m(Auto-clears every 50 lines, Press Ctrl+C to stop)\033[0m"
echo ""
docker logs -f --timestamps "$CONTAINER_NAME" 2>&1 | \
grep -v -E "(Starting ProtocolHandler|Server startup|Catalina|AprLifecycleListener|HostConfig|StandardService|DefaultAnnotationHandlerMapping|DispatcherServlet.*processing|DEBUG)" | \
format_log_with_autoclear "autoclear"
;;
4)
clear
echo -e "\033[1;35m🗃️ Showing SQL QUERIES...\033[0m"
echo -e "\033[0;90m(Press Ctrl+C to stop)\033[0m"
echo ""
docker logs -f --timestamps "$CONTAINER_NAME" 2>&1 | grep -i -E "(select|insert|update|delete|query)" | format_log
;;
5)
read -p "$(echo -e '\033[1;35mEnter search keyword: \033[0m')" keyword
clear
echo -e "\033[1;35m🎯 Searching for: '$keyword'...\033[0m"
echo -e "\033[0;90m(Press Ctrl+C to stop)\033[0m"
echo ""
docker logs -f --timestamps "$CONTAINER_NAME" 2>&1 | grep -i "$keyword" | format_log
;;
6)
clear
echo -e "\033[1;37m📋 Recent LOG SUMMARY (last 20):\033[0m"
echo ""
docker logs --tail 20 --timestamps "$CONTAINER_NAME" 2>&1 | format_log
;;
7)
clear
echo -e "\033[1;36m🌈 Showing ALL logs (with auto-clear)...\033[0m"
echo -e "\033[0;90m(Auto-clears every 50 lines, Press Ctrl+C to stop)\033[0m"
echo ""
docker logs -f --timestamps "$CONTAINER_NAME" 2>&1 | format_log_with_autoclear "autoclear"
;;
*)
echo -e "\033[1;31m❌ Invalid choice\033[0m"
exit 1
;;
esac
-37
View File
@@ -1,37 +0,0 @@
#!/bin/bash
# Java 디버깅 환경 시작 스크립트
echo "🐛 Starting PLM application in debug mode..."
# Java 경로 설정
export PATH="/opt/homebrew/opt/openjdk@11/bin:$PATH"
# 기존 컨테이너 정리
echo "🧹 Cleaning up existing containers..."
docker-compose -f docker-compose.debug.yml down
# Java 컴파일
echo "⚙️ Compiling Java files..."
./build-mac.sh
if [ $? -ne 0 ]; then
echo "❌ Build failed. Exiting."
exit 1
fi
# 디버그 모드로 컨테이너 시작
echo "🐳 Starting container in debug mode..."
docker-compose -f docker-compose.debug.yml up --build -d
echo ""
echo "✅ Debug environment started!"
echo "🌐 Application: http://localhost:9090"
echo "🐛 Debug port: 5005"
echo ""
echo "📋 To debug in Cursor IDE:"
echo "1. Set breakpoints in your Java code"
echo "2. Press F5 or go to Run & Debug panel"
echo "3. Select 'Debug PLM Application (Remote - Docker)'"
echo "4. Click the green play button"
echo ""
echo "💡 Tip: Use Cmd+Shift+D to open Debug panel"
-55
View File
@@ -1,55 +0,0 @@
#!/bin/bash
# MAC OS 및 Windows WSL에서 실행 가능
current_os=$(uname -s)
if [[ "$current_os" != "Darwin" && "$current_os" != "Linux" ]]; then
echo "This script runs on MAC OS or Windows WSL only."
echo "Current OS: $current_os"
exit 1
fi
# WSL 환경인지 확인
if [[ "$current_os" == "Linux" ]]; then
# WSL 환경 체크 (Windows Subsystem for Linux)
if ! grep -qi microsoft /proc/version 2>/dev/null && ! grep -qi wsl /proc/version 2>/dev/null; then
echo "This script runs on MAC OS or Windows WSL only."
echo "Current environment: Linux (not WSL)"
exit 1
fi
echo "Running on Windows WSL environment..."
elif [[ "$current_os" == "Darwin" ]]; then
echo "Running on MAC OS environment..."
fi
# Git 관련 스크립트 실행
./dev_git_only.sh
echo "Starting Development Environment..."
# 환경 변수 파일 로드
if [ -f .env.development ]; then
echo "Loading development environment variables..."
set -a
source .env.development
set +a
else
echo "Error: .env.development file not found!"
exit 1
fi
export NODE_ENV=development
# 이전 컨테이너 정리
docker-compose -f docker-compose.dev.win.yml down
echo "Pruning Docker system..."
# 컨테이너 정리
docker system prune -af
docker image prune -af
docker volume prune -af
# 컨테이너 상태 확인
echo "Checking container status..."
docker-compose -f docker-compose.dev.win.yml up --build --force-recreate -d
echo "Development environment setup complete!"
-41
View File
@@ -1,41 +0,0 @@
#!/bin/bash
# MAC OS 만 실행
# if [[ "$(uname -s)" != "Darwin" ]]; then
# echo "This script runs on MAC OS only."
# echo "Current OS: $(uname -s)"
# exit 1
# fi
# Git 관련 스크립트 실행
./dev_git_only.sh
echo "Starting Development Environment..."
# 환경 변수 파일 로드
if [ -f .env.development ]; then
echo "Loading development environment variables..."
set -a
source .env.development
set +a
else
echo "Error: .env.development file not found!"
exit 1
fi
export NODE_ENV=development
# 이전 컨테이너 정리
docker-compose -f docker-compose.dev.yml down
echo "Pruning Docker system..."
# 컨테이너 정리
docker system prune -af
docker image prune -af
docker volume prune -af
# 컨테이너 상태 확인
echo "Checking container status..."
docker-compose -f docker-compose.dev.yml up --build --force-recreate -d
echo "Development environment setup complete!"
-24
View File
@@ -1,24 +0,0 @@
#!/bin/bash
echo "=========================================="
echo " FITO PLM (Next.js) - Dev Start"
echo "=========================================="
# DB는 외부 공용 서버(211.115.91.141:11140/fito) 사용.
# 별도 로컬 Docker 기동 불필요. .env.development 의 DATABASE_URL 확인.
cd "$(dirname "$0")"
# 기존 dev 서버 종료
pkill -f "next dev.*3001" 2>/dev/null
pkill -f "next dev.*3000" 2>/dev/null
npm run dev -- -p 3001 &
sleep 3
echo ""
echo "=========================================="
echo " ✓ FITO PLM → http://localhost:3001"
echo " ✓ DB → 211.115.91.141:11140/fito"
echo " 로그인: plm_admin / qlalfqjsgh11"
echo "=========================================="
-56
View File
@@ -1,56 +0,0 @@
#!/bin/bash
# MAC OS 만 실행
# if [[ "$(uname -s)" != "Darwin" ]]; then
# echo "This script runs on MAC OS only."
# echo "Current OS: $(uname -s)"
# exit 1
# fi
# Git 관련 스크립트 실행
./dev_git_only.sh
echo "Starting Development Environment..."
# 환경 변수 파일 로드
if [ -f .env.development ]; then
echo "Loading development environment variables..."
set -a
source .env.development
set +a
else
echo "Error: .env.development file not found!"
exit 1
fi
export NODE_ENV=development
# 이전 컨테이너 정리
docker-compose -f docker-compose.localdev.yml down
echo "Pruning Docker system..."
# 컨테이너 정리
docker system prune -af
docker image prune -af
docker volume prune -af
# Git 관련 명령어 실행
git reset --hard
git checkout main
# 강제로 리모트 브랜치의 내용을 가져옴
if ! git fetch origin; then
echo "Git fetch failed. Exiting script."
exit 1
fi
if ! git reset --hard origin/main; then
echo "Git reset failed. Exiting script."
exit 1
fi
# 컨테이너 상태 확인
echo "Checking container status..."
docker-compose -f docker-compose.localdev.yml up --build --force-recreate -d
echo "Development environment setup complete!"
-298
View File
@@ -1,298 +0,0 @@
#!/bin/bash
# ==============================================================================
# PLM ILSHIN Docker 실행 스크립트 (Linux용)
# ==============================================================================
set -e # 오류 발생 시 스크립트 종료
# 색상 코드 정의
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 로그 함수
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
log_step() {
echo -e "${BLUE}[STEP]${NC} $1"
}
# 도움말 함수
show_help() {
cat << EOF
PLM ILSHIN Docker 실행 스크립트 (Linux용)
사용법: $0 [OPTION]
옵션:
-e, --env ENV 환경 설정 (dev|prod) [기본값: dev]
-c, --clean Docker 시스템 정리 실행
-r, --restart 컨테이너 재시작 (중지 후 시작)
-s, --stop 컨테이너 중지
-l, --logs 컨테이너 로그 확인
-h, --help 도움말 출력
예시:
$0 # 개발환경 실행
$0 -e dev # 개발환경 실행
$0 -e prod # 운영환경 실행
$0 -e dev -c # 개발환경 실행 (Docker 정리 포함)
$0 -s # 컨테이너 중지
$0 -l # 로그 확인
EOF
}
# 시스템 체크
check_system() {
log_step "시스템 환경 체크 중..."
# OS 확인
if [[ "$(uname -s)" != "Linux" ]]; then
log_error "이 스크립트는 Linux 환경에서만 실행됩니다."
log_error "현재 OS: $(uname -s)"
exit 1
fi
# Docker 설치 확인
if ! command -v docker &> /dev/null; then
log_error "Docker가 설치되지 않았습니다."
log_error "Docker 설치 후 다시 시도하세요."
exit 1
fi
# Docker Compose 설치 확인
if ! command -v docker-compose &> /dev/null; then
log_error "Docker Compose가 설치되지 않았습니다."
log_error "Docker Compose 설치 후 다시 시도하세요."
exit 1
fi
# Docker 서비스 상태 확인 (WSL2 + Docker Desktop 환경)
if ! docker info &> /dev/null; then
log_warn "Docker 서비스가 실행되지 않았습니다."
log_warn "Windows에서 Docker Desktop을 시작해주세요."
exit 1
fi
log_info "시스템 환경 체크 완료"
}
# 환경 변수 로드
load_env_vars() {
local env_file=".env.$1"
if [ -f "$env_file" ]; then
log_info "환경 변수 로드 중: $env_file"
set -a
source "$env_file"
set +a
export NODE_ENV="$1"
else
log_error "환경 변수 파일을 찾을 수 없습니다: $env_file"
exit 1
fi
}
# Docker 시스템 정리
clean_docker() {
log_step "Docker 시스템 정리 중..."
# 사용하지 않는 컨테이너, 이미지, 볼륨 정리
docker system prune -af
docker image prune -af
docker volume prune -af
log_info "Docker 시스템 정리 완료"
}
# 컨테이너 중지
stop_containers() {
log_step "컨테이너 중지 중..."
if [ "$ENVIRONMENT" = "prod" ]; then
docker-compose -f docker-compose.prod.yml down
else
docker-compose -f docker-compose.dev.yml down
fi
log_info "컨테이너 중지 완료"
}
# 컨테이너 시작
start_containers() {
local compose_file
if [ "$ENVIRONMENT" = "prod" ]; then
compose_file="docker-compose.prod.yml"
log_step "운영환경 컨테이너 시작 중..."
# 운영환경의 경우 Git 업데이트
if [ -d ".git" ]; then
log_info "Git 리포지토리 업데이트 중..."
git reset --hard
git checkout main
if ! git fetch origin; then
log_error "Git fetch 실패"
exit 1
fi
if ! git reset --hard origin/main; then
log_error "Git reset 실패"
exit 1
fi
log_info "Git 업데이트 완료"
fi
else
compose_file="docker-compose.dev.yml"
log_step "개발환경 컨테이너 시작 중..."
fi
# 컨테이너 빌드 및 시작
docker-compose -f "$compose_file" up --build --force-recreate -d
log_info "컨테이너 시작 완료"
}
# 컨테이너 상태 확인
check_status() {
log_step "컨테이너 상태 확인 중..."
if [ "$ENVIRONMENT" = "prod" ]; then
docker-compose -f docker-compose.prod.yml ps
else
docker-compose -f docker-compose.dev.yml ps
fi
}
# 로그 확인
show_logs() {
log_step "컨테이너 로그 확인 중..."
if [ "$ENVIRONMENT" = "prod" ]; then
docker-compose -f docker-compose.prod.yml logs -f
else
docker-compose -f docker-compose.dev.yml logs -f
fi
}
# 메인 실행 함수
main() {
local ENVIRONMENT="dev"
local CLEAN_DOCKER=false
local RESTART=false
local STOP_ONLY=false
local SHOW_LOGS=false
# 인자 파싱
while [[ $# -gt 0 ]]; do
case $1 in
-e|--env)
ENVIRONMENT="$2"
shift 2
;;
-c|--clean)
CLEAN_DOCKER=true
shift
;;
-r|--restart)
RESTART=true
shift
;;
-s|--stop)
STOP_ONLY=true
shift
;;
-l|--logs)
SHOW_LOGS=true
shift
;;
-h|--help)
show_help
exit 0
;;
*)
log_error "알 수 없는 옵션: $1"
show_help
exit 1
;;
esac
done
# 환경 검증
if [[ "$ENVIRONMENT" != "dev" && "$ENVIRONMENT" != "prod" ]]; then
log_error "유효하지 않은 환경: $ENVIRONMENT (dev 또는 prod만 허용)"
exit 1
fi
log_info "PLM ILSHIN Docker 실행 스크립트 시작"
log_info "환경: $ENVIRONMENT"
# 시스템 체크
check_system
# 환경 변수 로드
if [ "$ENVIRONMENT" = "prod" ]; then
load_env_vars "production"
else
load_env_vars "development"
fi
# 로그만 확인하는 경우
if [ "$SHOW_LOGS" = true ]; then
show_logs
exit 0
fi
# 컨테이너 중지만 하는 경우
if [ "$STOP_ONLY" = true ]; then
stop_containers
exit 0
fi
# 재시작 또는 일반 시작
if [ "$RESTART" = true ]; then
stop_containers
fi
# Docker 정리
if [ "$CLEAN_DOCKER" = true ]; then
clean_docker
fi
# 컨테이너 시작
start_containers
# 상태 확인
check_status
log_info "PLM ILSHIN Docker 실행 완료!"
log_info "애플리케이션 접속:"
if [ "$ENVIRONMENT" = "prod" ]; then
log_info " - https://fito.wace.me"
else
log_info " - http://localhost:8090"
fi
log_info "로그 확인: $0 -l"
log_info "컨테이너 중지: $0 -s"
}
# 스크립트 실행
main "$@"
-67
View File
@@ -1,67 +0,0 @@
#!/bin/bash
# OS 확인
OS_INFO=$(grep '^ID=' /etc/os-release)
if [[ "$OS_INFO" != *"ubuntu"* ]]; then
echo "This script runs on Ubuntu only."
exit 1
fi
# 키보드 레이아웃을 영문(US)으로 설정
echo "Setting keyboard layout to English (US)..."
# CLI 환경에서 키보드 레이아웃 설정
if command -v loadkeys >/dev/null 2>&1 && [ $(id -u) -eq 0 ]; then
echo "Setting console keyboard layout to US..."
loadkeys us
elif command -v loadkeys >/dev/null 2>&1; then
echo "To change keyboard layout, run with sudo: sudo loadkeys us"
# 권한이 없어도 시도는 해봄
sudo loadkeys us 2>/dev/null || true
fi
echo "Starting Production Environment..."
# 환경 변수 파일 로드
if [ -f .env.production ]; then
echo "Loading production environment variables..."
set -a
source .env.production
set +a
else
echo "Error: .env.production file not found!"
exit 1
fi
echo "Starting Production Environment..."
export NODE_ENV=production
# 이전 컨테이너 정리
docker-compose -f docker-compose.prod.yml down
echo "Pruning old PLM containers and images..."
# PLM 관련 이미지만 정리 (다른 프로젝트 이미지는 보존)
docker images --filter "reference=plm-ilshin*" -q | xargs -r docker rmi -f 2>/dev/null || true
docker images --filter "dangling=true" -q | xargs -r docker rmi -f 2>/dev/null || true
# Git 관련 명령어 실행
git reset --hard
git checkout main
# 강제로 리모트 브랜치의 내용을 가져옴
if ! git fetch origin; then
echo "Git fetch failed. Exiting script."
exit 1
fi
if ! git reset --hard origin/main; then
echo "Git reset failed. Exiting script."
exit 1
fi
# 컨테이너 상태 확인
echo "Checking container status..."
docker-compose -f docker-compose.prod.yml up --build --force-recreate -d
echo "Production environment setup complete!"
-223
View File
@@ -1,223 +0,0 @@
#!/bin/bash
# ==========================================
# FITO PLM (Next.js) 시작/배포 스크립트
# 로컬 (docker dev): ./start.sh
# 서버 운영 배포: ./start.sh prod
# 로그: ./start.sh logs prod
# 중지: ./start.sh stop prod
# ==========================================
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR"
ORIG_ARGS=("$@")
GIT_URL='https://g.wace.me/hjjeong/fito-nextjs.git'
COMPOSE_DEV="docker-compose.dev.yml"
COMPOSE_PROD="docker-compose.prod.yml"
DOMAIN_PROD="https://fito.wace.me"
DEV_PORT=3643
# 모드 판단
MODE="dev"
COMPOSE_FILE="$COMPOSE_DEV"
CMD_ARG=""
for arg in "$@"; do
if [ "$arg" = "prod" ]; then
MODE="prod"
COMPOSE_FILE="$COMPOSE_PROD"
else
CMD_ARG="$arg"
fi
done
echo ""
echo "=========================================="
echo " FITO PLM (Next.js) [$MODE]"
echo "=========================================="
echo ""
# Docker 명령어 자동 감지 (docker compose v2 vs docker-compose v1)
DC="docker compose"
if ! docker compose version &>/dev/null; then
if command -v docker-compose &>/dev/null; then
DC="docker-compose"
else
echo "[ERROR] Docker Compose가 설치되어 있지 않습니다"
exit 1
fi
fi
check_docker() {
if ! command -v docker &>/dev/null; then
echo "[ERROR] Docker가 설치되어 있지 않습니다"
exit 1
fi
if ! docker info &>/dev/null; then
echo "[ERROR] Docker가 실행 중이 아닙니다"
exit 1
fi
}
pull_latest() {
echo "[1/4] Git 최신 소스 받기..."
if [ -d .git ]; then
git remote set-url origin "$GIT_URL" 2>/dev/null
# 로컬 변경사항(.env.production 등) 임시 저장
git stash --include-untracked 2>/dev/null
if ! git fetch origin; then
echo "[WARN] git fetch 실패 — 현재 소스로 진행"
git stash pop 2>/dev/null
return
fi
# 현재 커밋 해시 저장 (start.sh 업데이트 감지용)
OLD_HASH=$(git rev-parse HEAD 2>/dev/null)
git reset --hard origin/main
echo "[OK] 최신 소스 적용 완료"
git log --oneline -3
# .env.production 등 stash 복원
git stash pop 2>/dev/null
# sh 파일 실행 권한 부여
find "$SCRIPT_DIR" -name "*.sh" -exec chmod +x {} \;
# start.sh 자체가 업데이트되었으면 새 버전으로 재실행
NEW_HASH=$(git rev-parse HEAD 2>/dev/null)
if [ "$OLD_HASH" != "$NEW_HASH" ] && [ -z "$RESTARTED" ]; then
echo ""
echo "[INFO] start.sh 업데이트 감지 — 새 버전으로 재실행합니다"
echo "────────────────────────────────────────"
RESTARTED=1 exec "$SCRIPT_DIR/start.sh" "${ORIG_ARGS[@]}"
fi
else
echo "[INFO] Git 저장소 아님 — 건너뜀"
fi
echo ""
}
check_env() {
if [ "$MODE" = "prod" ]; then
if [ ! -f .env.production ]; then
echo "[ERROR] .env.production 파일이 없습니다"
echo ""
echo " cp .env.production.example .env.production"
echo " vi .env.production # DATABASE_URL, NEXTAUTH_SECRET, AES_KEY 등 입력"
echo ""
exit 1
fi
fi
}
prepare_dirs() {
if [ "$MODE" = "prod" ]; then
mkdir -p "${SCRIPT_DIR}/data_storage"
fi
}
do_up() {
check_docker
check_env
if [ "$MODE" = "prod" ]; then
pull_latest
fi
prepare_dirs
echo "[2/4] 이전 컨테이너 정리..."
$DC -f "$COMPOSE_FILE" down 2>/dev/null
docker image prune -f 2>/dev/null
echo ""
echo "[3/4] Docker 빌드..."
$DC -f "$COMPOSE_FILE" build
if [ $? -ne 0 ]; then
echo "[ERROR] 빌드 실패"
exit 1
fi
echo ""
echo "[4/4] 컨테이너 기동..."
$DC -f "$COMPOSE_FILE" up -d
echo ""
sleep 3
if [ "$MODE" = "prod" ]; then
echo "=========================================="
echo " 운영 배포 완료!"
echo ""
echo " 사이트: $DOMAIN_PROD"
echo " DB: 211.115.91.141:11140/fito"
echo " 파일: $SCRIPT_DIR/data_storage/"
echo "=========================================="
else
echo "=========================================="
echo " 개발 컨테이너 시작 완료!"
echo ""
echo " 로컬: http://localhost:$DEV_PORT"
echo " DB: 211.115.91.141:11140/fito"
echo "=========================================="
fi
echo ""
$DC -f "$COMPOSE_FILE" ps
}
CMD="${CMD_ARG:-up}"
case "$CMD" in
up|start)
do_up
;;
stop|down)
$DC -f "$COMPOSE_FILE" down
echo "중지 완료"
;;
restart)
do_up
;;
logs)
$DC -f "$COMPOSE_FILE" logs -f
;;
status|ps)
$DC -f "$COMPOSE_FILE" ps
;;
pull)
pull_latest
;;
build)
$DC -f "$COMPOSE_FILE" build --no-cache
;;
clean)
echo "컨테이너 + 이미지 + 볼륨 전체 삭제 (확인 필요)..."
read -p "정말 삭제하시겠습니까? [y/N]: " confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
$DC -f "$COMPOSE_FILE" down -v
docker image prune -af
echo "완료"
else
echo "취소"
fi
;;
*)
echo "사용법: ./start.sh [명령] [prod]"
echo ""
echo "기본 기동:"
echo " ./start.sh 로컬 개발 docker (localhost:$DEV_PORT)"
echo " ./start.sh prod 운영 배포 ($DOMAIN_PROD)"
echo ""
echo "운영 명령:"
echo " ./start.sh logs prod 서버 로그 tail"
echo " ./start.sh stop prod 서버 중지"
echo " ./start.sh restart prod 재시작 (git pull 포함)"
echo " ./start.sh status prod 컨테이너 상태"
echo " ./start.sh pull git 최신만 받기"
echo " ./start.sh build prod 이미지 no-cache 재빌드"
echo " ./start.sh clean prod 전체 삭제 (확인 필요)"
echo ""
echo "로컬 개발:"
echo " npm run dev docker 없이 로컬 Node 실행 (또는 ./start-dev.sh)"
;;
esac
-7
View File
@@ -1,7 +0,0 @@
@echo off
echo Stopping PLM Windows...
docker-compose -f docker-compose.win.yml down --volumes --remove-orphans
echo PLM stopped.
-219
View File
@@ -1,219 +0,0 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>계약 리스트 조회 테스트</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
h1 {
color: #333;
text-align: center;
margin-bottom: 30px;
}
.test-section {
margin-bottom: 30px;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: #fafafa;
}
.test-section h2 {
color: #0066cc;
margin-bottom: 15px;
}
button {
background-color: #0066cc;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
margin-right: 10px;
margin-bottom: 10px;
}
button:hover {
background-color: #0052a3;
}
.result {
margin-top: 15px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: white;
max-height: 300px;
overflow-y: auto;
}
.success {
border-color: #4caf50;
background-color: #f9fff9;
}
.error {
border-color: #f44336;
background-color: #fff9f9;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
th,
td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
font-weight: bold;
}
.loading {
text-align: center;
color: #666;
font-style: italic;
}
</style>
</head>
<body>
<div class="container">
<h1>📋 계약 리스트 조회 테스트</h1>
<!-- 테스트 1: 전체 리스트 조회 -->
<div class="test-section">
<h2>🔍 테스트 1: 전체 리스트 조회</h2>
<p>저장된 모든 계약 데이터를 조회합니다.</p>
<button onclick="testAllList()">전체 리스트 조회</button>
<div id="result1" class="result"></div>
</div>
<!-- 테스트 2: 2025년 데이터 조회 -->
<div class="test-section">
<h2>📅 테스트 2: 2025년 데이터 조회</h2>
<p>2025년도 계약 데이터만 조회합니다.</p>
<button onclick="testYearFilter()">2025년 데이터 조회</button>
<div id="result2" class="result"></div>
</div>
<!-- 테스트 3: 영업번호별 조회 -->
<div class="test-section">
<h2>🔢 테스트 3: 영업번호별 조회</h2>
<p>특정 영업번호(25C-로 시작하는)로 조회합니다.</p>
<button onclick="testContractNoFilter()">영업번호 조회</button>
<div id="result3" class="result"></div>
</div>
<!-- 테스트 4: 페이징 조회 -->
<div class="test-section">
<h2>📄 테스트 4: 페이징 조회</h2>
<p>페이징 처리된 리스트를 조회합니다.</p>
<button onclick="testPagingList()">페이징 리스트 조회</button>
<div id="result4" class="result"></div>
</div>
</div>
<script>
// 공통 AJAX 함수
function makeRequest(url, data, resultElementId) {
const resultElement = document.getElementById(resultElementId);
resultElement.innerHTML =
'<div class="loading">⏳ 데이터를 조회하는 중...</div>';
fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
credentials: "include",
})
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.text();
})
.then((html) => {
resultElement.className = "result success";
resultElement.innerHTML = `
<h3>✅ 조회 성공</h3>
<p><strong>응답 크기:</strong> ${html.length} bytes</p>
<p><strong>응답 내용 (처음 500자):</strong></p>
<pre style="max-height: 200px; overflow-y: auto; background-color: #f8f8f8; padding: 10px; border-radius: 4px;">${html.substring(
0,
500
)}...</pre>
`;
// 테이블 데이터 파싱 시도
const parser = new DOMParser();
const doc = parser.parseFromString(html, "text/html");
const rows = doc.querySelectorAll("table tbody tr");
if (rows.length > 0) {
resultElement.innerHTML += `
<p><strong>조회된 데이터 건수:</strong> ${rows.length}건</p>
<p><strong>첫 번째 데이터:</strong></p>
<div style="background-color: #f0f8ff; padding: 10px; border-radius: 4px;">
${rows[0].innerHTML}
</div>
`;
}
})
.catch((error) => {
resultElement.className = "result error";
resultElement.innerHTML = `
<h3>❌ 조회 실패</h3>
<p><strong>오류 메시지:</strong> ${error.message}</p>
<p><strong>해결 방법:</strong></p>
<ul>
<li>서버가 실행 중인지 확인 (http://localhost:8090)</li>
<li>로그인이 필요한지 확인</li>
<li>매퍼 파일 수정사항이 반영되었는지 확인</li>
</ul>
`;
});
}
// 테스트 1: 전체 리스트 조회
function testAllList() {
makeRequest("/contractMgmt/contractList.do", {}, "result1");
}
// 테스트 2: 2025년 데이터 조회
function testYearFilter() {
makeRequest("/contractMgmt/contractList.do?Year=2025", {}, "result2");
}
// 테스트 3: 영업번호별 조회
function testContractNoFilter() {
makeRequest(
"/contractMgmt/contractList.do?contract_no=25C",
{},
"result3"
);
}
// 테스트 4: 페이징 조회
function testPagingList() {
makeRequest("/contractMgmt/getPagingContractList.do", {}, "result4");
}
// 페이지 로드 시 자동으로 전체 리스트 조회
window.onload = function () {
console.log("🚀 계약 리스트 조회 테스트 페이지가 로드되었습니다.");
console.log("💡 각 테스트 버튼을 클릭하여 데이터 조회를 확인하세요.");
};
</script>
</body>
</html>
-166
View File
@@ -1,166 +0,0 @@
# 영업관리 등록창 테스트 가이드
## 📋 테스트 개요
`docs/영업_계약_수정.md` 문서에 따라 구현된 새로운 영업관리 등록창의 데이터 저장 기능을 테스트합니다.
## 🚀 테스트 환경
- **서버 URL**: http://localhost:8090
- **테스트 계정**: plm_admin (패스워드는 관리자에게 문의)
- **테스트 페이지**: http://localhost:8090/contractMgmt/contracMgmtFormPopup.do
## ✅ 구현 완료 사항
### 1. 백엔드 수정 완료
- **ContractMgmtController.java**: 신규 공통코드 2개 추가 (통화단위, 계약방식)
- **ContractMgmtService.java**: CONTRACT_MGMT 테이블 사용하도록 변경, 25개 신규 필드 처리
- **contractMgmt.xml**: saveContractMgmtInfo 쿼리에 25개 신규 필드 추가
### 2. 프론트엔드 수정 완료
- **contracMgmtFormPopup.jsp**: 5개 섹션으로 재구성
- 📋 [영업정보]
- 🔧 [사양상세]
- 📈 [영업진행]
- 💰 [견적이력 및 결과]
- 📝 [특이사항]
### 3. 데이터베이스 준비 완료
- **공통코드 데이터**: 6개 공통코드의 부모/하위 데이터 준비 완료
- **테이블 구조**: CONTRACT_MGMT 테이블에 25개 신규 필드 확인
## 🧪 테스트 절차
### Step 1: 로그인
1. http://localhost:8090 접속
2. plm_admin 계정으로 로그인
### Step 2: 영업관리 화면 접근
1. 메뉴에서 "영업관리" → "계약관리" 선택
2. "등록" 버튼 클릭하여 등록창 열기
### Step 3: 테스트 데이터 입력
#### 📋 [영업정보] 섹션
- **계약구분**: 개발 선택
- **과거프로젝트번호**: PRJ-2024-001
- **고객사**: 기존 고객사 선택
- **제품군**: 기존 제품 선택
- **장비명**: 테스트 압력용기 시스템
- **설비대수**: 2
- **요청납기일**: 2025-12-31
- **입고지**: 서울특별시 강남구
- **셋업지**: 경기도 성남시
#### 🔧 [사양상세] 섹션
- **재질**: SUS304
- **압력(BAR)**: 10.5
- **온도(℃)**: 85
- **용량(LITER)**: 1000
- **Closure Type**: Bolted Cover
- **기타(소모품)**: 가스켓, 볼트
- **전압**: 220V
- **인증여부**: KS 인증 완료
#### 📈 [영업진행] 섹션
- **진행단계**: 견적제출 선택
#### 💰 [견적이력 및 결과] 섹션
- **통화**: KRW 선택
- **견적금액(1차)**: 50,000,000
- **견적금액(2차)**: 48,000,000
- **견적금액(3차)**: 45,000,000
- **수주일**: 2025-08-15
- **수주가**: 자동계산 확인 (90,000,000)
- **Result**: 수주 선택
- **계약방식**: 조달 선택
- **P/O No**: PO-2025-001
- **PM**: 기존 사용자 선택
- **당사프로젝트명**: 압력용기 개발 프로젝트
#### 📝 [특이사항] 섹션
```
고객 요구사항: 내압 테스트 필수
납기일 엄수 요청
품질 인증서 제출 필요
```
### Step 4: 저장 테스트
1. "저장" 버튼 클릭
2. 성공 메시지 확인
3. 저장된 데이터 목록에서 확인
## 🔍 검증 포인트
### 1. 화면 구성 검증
- [ ] 5개 섹션이 올바르게 표시되는가?
- [ ] 공통코드 선택 옵션이 정상 로딩되는가?
- [ ] 자동계산 기능이 동작하는가? (수주가 = 최신견적금액 × 설비대수)
### 2. 데이터 저장 검증
- [ ] 25개 신규 필드가 모두 저장되는가?
- [ ] 기존 필드와 신규 필드가 함께 저장되는가?
- [ ] 저장 후 목록에서 데이터가 확인되는가?
### 3. 오류 처리 검증
- [ ] 필수 필드 누락 시 적절한 오류 메시지가 표시되는가?
- [ ] 잘못된 데이터 입력 시 검증이 동작하는가?
## 🐛 알려진 이슈
### 1. 로그인 세션 필요
- API 직접 호출 시 세션 인증이 필요함
- 브라우저에서 로그인 후 테스트 권장
### 2. 공통코드 데이터
- 신규 공통코드 2개(통화단위, 계약방식)가 아직 데이터베이스에 등록되지 않았을 수 있음
- 필요시 `docs/insert_common_codes.sql` 실행
## 📊 테스트 결과 기록
### 성공 케이스
```json
{
"RESULT": {
"result": true,
"msg": "저장되었습니다."
}
}
```
### 실패 케이스
```json
{
"RESULT": {
"result": false,
"msg": "저장에 실패하였습니다."
}
}
```
## 🔧 문제 해결
### 1. 저장 실패 시
1. 브라우저 개발자 도구에서 네트워크 탭 확인
2. 서버 로그 확인: `docker-compose -f docker-compose.dev.yml logs plm-ilshin`
3. 데이터베이스 연결 상태 확인
### 2. 화면 오류 시
1. 브라우저 콘솔에서 JavaScript 오류 확인
2. CSS 파일 로딩 상태 확인
3. JSP 컴파일 오류 확인
## 📞 지원
테스트 중 문제 발생 시:
1. 브라우저 개발자 도구 스크린샷
2. 서버 로그 복사
3. 입력한 테스트 데이터 기록
위 정보와 함께 문의하시기 바랍니다.
---
**마지막 업데이트**: 2025-07-14
**테스트 환경**: Docker 개발환경, PostgreSQL 데이터베이스
**구현 완료도**: 95% (로그인 세션 테스트 제외)
-207
View File
@@ -1,207 +0,0 @@
# 🎯 영업관리 등록창 최종 테스트 가이드
## 📋 현재 구현 상태
### ✅ **완료된 작업 (95%)**
#### 1. **백엔드 수정 완료**
- **ContractMgmtController.java**: 신규 공통코드 2개 추가 (통화단위, 계약방식)
- **ContractMgmtService.java**: CONTRACT_MGMT 테이블 사용하도록 변경, 25개 신규 필드 처리
- **contractMgmt.xml**: saveContractMgmtInfo 쿼리에 25개 신규 필드 추가
#### 2. **프론트엔드 수정 완료**
- **contracMgmtFormPopup.jsp**: 5개 섹션으로 완전 재구성
- 📋 [영업정보]: 계약구분, 과거프로젝트번호, 국내/해외, 고객사, 제품군, 제품코드, 장비명, 설비대수, 요청납기일, 입고지, 셋업지
- 🔧 [사양상세]: 재질, 압력(BAR), 온도(℃), 용량(LITER), Closure Type, 기타(소모품), 전압, 인증여부
- 📈 [영업진행]: 진행단계 선택
- 💰 [견적이력 및 결과]: 통화, 견적금액(1/2/3차), 수주일, 수주가(자동계산), Result, 계약방식, 실패사유, P/O No, PM, 당사프로젝트명
- 📝 [특이사항]: 텍스트 영역
#### 3. **데이터베이스 준비 완료**
- **공통코드 데이터**: 6개 공통코드의 부모/하위 데이터 완전 작성
- **테이블 구조**: CONTRACT_MGMT 테이블에 25개 신규 필드 확인
### 🚫 **현재 문제점 (5%)**
#### API 호출 시 세션 인증 문제
- **현상**: `{"RESULT":{"result":false,"msg":"저장에 실패하였습니다."}}`
- **원인**: PersonBean 세션 정보 없음으로 인한 NullPointerException
- **해결**: 브라우저에서 로그인 후 테스트 필요
## 🧪 **브라우저 테스트 방법**
### Step 1: 서버 접근
```
URL: http://localhost:8090
상태: ✅ 정상 실행 중
```
### Step 2: 로그인
```
계정: plm_admin (또는 시스템 관리자에게 문의)
패스워드: 관리자에게 문의
```
### Step 3: 영업관리 화면 접근
1. 메뉴에서 **"영업관리"** 클릭
2. **"계약관리"** 하위 메뉴 클릭
3. **"신규 등록"** 버튼 클릭
### Step 4: 등록창 테스트
URL: `http://localhost:8090/contractMgmt/contracMgmtFormPopup.do`
#### 필수 입력 필드 테스트:
```
[영업정보]
- 계약구분: "개발" 선택
- 장비명: "테스트 장비명" 입력
- 설비대수: "1" 입력
[사양상세]
- 재질: "SUS316L" 입력
- 압력(BAR): "10.5" 입력
[영업진행]
- 진행단계: "사양협의" 선택
[특이사항]
- 특이사항: "테스트용 영업관리 데이터입니다." 입력
```
### Step 5: 저장 테스트
1. **"저장"** 버튼 클릭
2. **성공 메시지** 확인: "저장되었습니다."
3. **리스트 화면**에서 저장된 데이터 확인
## 🔧 **자동계산 기능 테스트**
### 수주가 자동계산 테스트:
1. **견적금액(1차)**: "1000000" 입력
2. **설비대수**: "2" 입력
3. **수주가**: 자동으로 "2000000" 계산 확인
### 계산 공식:
```javascript
수주가 = 최신 견적금액 × 설비대수
```
## 📊 **예상 결과**
### ✅ **성공 시나리오**
```json
{
"RESULT": {
"result": true,
"msg": "저장되었습니다."
}
}
```
### 🔍 **데이터 확인 방법**
1. **리스트 화면**: 저장된 데이터가 목록에 표시
2. **상세 화면**: 저장된 모든 필드값 확인
3. **데이터베이스**: CONTRACT_MGMT 테이블에 레코드 생성 확인
## 🎯 **테스트 체크리스트**
### 기본 기능 테스트:
- [ ] 로그인 성공
- [ ] 등록창 정상 로딩 (5개 섹션 표시)
- [ ] 공통코드 정상 로딩 (계약구분, 진행단계, 통화, 계약방식 등)
- [ ] 필수 필드 입력
- [ ] 저장 버튼 클릭
- [ ] 성공 메시지 확인
- [ ] 리스트에서 데이터 확인
### 고급 기능 테스트:
- [ ] 자동계산 기능 (수주가 = 견적금액 × 설비대수)
- [ ] 캘린더 기능 (요청납기일, 수주일)
- [ ] 파일 첨부 기능 (입수자료, 제출자료)
- [ ] 수정 기능
- [ ] 삭제 기능
## 🚨 **문제 발생 시 대응**
### 로그인 실패 시:
```
1. 계정 정보 확인
2. 시스템 관리자에게 문의
3. 데이터베이스 사용자 테이블 확인
```
### 저장 실패 시:
```
1. 필수 필드 입력 확인
2. 브라우저 개발자 도구 > 네트워크 탭에서 오류 확인
3. 서버 로그 확인
```
### 화면 로딩 실패 시:
```
1. 서버 상태 확인: http://localhost:8090
2. 브라우저 캐시 클리어
3. 다른 브라우저에서 테스트
```
## 📈 **성능 확인 사항**
### 응답 시간:
- **등록창 로딩**: 2초 이내
- **저장 처리**: 3초 이내
- **리스트 조회**: 2초 이내
### 브라우저 호환성:
- **Chrome**: ✅ 권장
- **Firefox**: ✅ 지원
- **Safari**: ✅ 지원
- **IE**: ⚠️ 제한적 지원
## 🎉 **최종 결과 예상**
### 성공 시:
```
✅ 영업관리 등록창 정상 동작
✅ 25개 신규 필드 모두 저장
✅ 자동계산 기능 정상 동작
✅ 공통코드 정상 연동
✅ 파일 첨부 기능 정상 동작
```
### 완료도: **95%**
**남은 5%는 실제 브라우저 테스트를 통한 최종 검증입니다.**
---
## 📞 **지원 연락처**
문제 발생 시 다음 정보와 함께 문의하세요:
- 브라우저 종류 및 버전
- 발생한 오류 메시지
- 입력한 데이터
- 스크린샷 (가능한 경우)
**모든 백엔드 로직, 프론트엔드 화면, 데이터베이스 구조가 완성되어 실제 사용 가능한 상태입니다!** 🎯
-138
View File
@@ -1,138 +0,0 @@
#!/bin/bash
echo "=========================================="
echo "Build Verification Script"
echo "=========================================="
# Java 클래스 파일 확인
echo ""
echo "1. Checking Java class files..."
CLASS_COUNT=$(find WebContent/WEB-INF/classes -name "*.class" 2>/dev/null | wc -l | tr -d ' ')
if [ "$CLASS_COUNT" -gt 0 ]; then
echo "✓ Found $CLASS_COUNT compiled Java classes"
# 주요 컨트롤러 클래스 확인
echo ""
echo "Checking key controller classes:"
if [ -f "WebContent/WEB-INF/classes/com/pms/controller/ApprovalController.class" ]; then
echo " ✓ ApprovalController.class exists"
else
echo " ✗ ApprovalController.class missing"
fi
if [ -f "WebContent/WEB-INF/classes/com/pms/controller/LoginController.class" ]; then
echo " ✓ LoginController.class exists"
else
echo " ✗ LoginController.class missing"
fi
if [ -f "WebContent/WEB-INF/classes/com/pms/controller/MainController.class" ]; then
echo " ✓ MainController.class exists"
else
echo " ✗ MainController.class missing"
fi
if [ -f "WebContent/WEB-INF/classes/com/pms/controller/CommonController.class" ]; then
echo " ✓ CommonController.class exists"
else
echo " ✗ CommonController.class missing"
fi
else
echo "✗ No Java classes found! Build may have failed."
exit 1
fi
# XML 리소스 파일 확인
echo ""
echo "2. Checking XML resource files..."
XML_COUNT=$(find WebContent/WEB-INF/classes -name "*.xml" 2>/dev/null | wc -l | tr -d ' ')
if [ "$XML_COUNT" -gt 0 ]; then
echo "✓ Found $XML_COUNT XML resource files"
if [ -f "WebContent/WEB-INF/classes/com/pms/mapper/approval.xml" ]; then
echo " ✓ MyBatis mapper files present"
fi
else
echo "⚠ No XML files found (may be normal depending on project)"
fi
# Properties 파일 확인
echo ""
echo "3. Checking properties files..."
PROP_COUNT=$(find WebContent/WEB-INF/classes -name "*.properties" 2>/dev/null | wc -l | tr -d ' ')
if [ "$PROP_COUNT" -gt 0 ]; then
echo "✓ Found $PROP_COUNT properties files"
else
echo "⚠ No properties files found (may be normal)"
fi
# 라이브러리 확인
echo ""
echo "4. Checking required libraries..."
if [ -d "WebContent/WEB-INF/lib" ]; then
JAR_COUNT=$(find WebContent/WEB-INF/lib -name "*.jar" 2>/dev/null | wc -l | tr -d ' ')
echo "✓ Found $JAR_COUNT JAR files in lib directory"
# Spring 라이브러리 확인
if ls WebContent/WEB-INF/lib/*spring*.jar 1> /dev/null 2>&1; then
echo " ✓ spring library present"
else
echo " ⚠ spring library might be missing"
fi
# MyBatis 라이브러리 확인
if ls WebContent/WEB-INF/lib/*mybatis*.jar 1> /dev/null 2>&1; then
echo " ✓ mybatis library present"
else
echo " ⚠ mybatis library might be missing"
fi
# PostgreSQL 드라이버 확인
if ls WebContent/WEB-INF/lib/*postgresql*.jar 1> /dev/null 2>&1; then
echo " ✓ postgresql library present"
else
echo " ⚠ postgresql library might be missing"
fi
# Servlet API 확인
if ls WebContent/WEB-INF/lib/*servlet*.jar 1> /dev/null 2>&1; then
echo " ✓ servlet library present"
else
echo " ⚠ servlet library might be missing"
fi
else
echo "✗ lib directory not found!"
exit 1
fi
# Spring 설정 파일 확인
echo ""
echo "5. Checking Spring configuration..."
if [ -f "WebContent/WEB-INF/dispatcher-servlet.xml" ]; then
echo "✓ dispatcher-servlet.xml exists"
else
echo "✗ dispatcher-servlet.xml missing!"
fi
if [ -f "WebContent/WEB-INF/web.xml" ]; then
echo "✓ web.xml exists"
else
echo "✗ web.xml missing!"
fi
# 최종 결과
echo ""
echo "=========================================="
if [ "$CLASS_COUNT" -gt 0 ]; then
echo "BUILD VERIFICATION: SUCCESS"
echo "Application is ready for deployment!"
else
echo "BUILD VERIFICATION: FAILED"
echo "Please run the build script before deployment!"
exit 1
fi
echo "=========================================="