Merge branch 'feat/infer_dev_260107' of https://kamco.gitea.gs.dabeeo.com/dabeeo/kamco-dabeeo-backoffice into feat/infer_dev_260107
# Conflicts: # src/main/resources/application-local.yml
This commit is contained in:
571
gradle/mac/pack_offline_bundle_airgap_macos.sh
Executable file
571
gradle/mac/pack_offline_bundle_airgap_macos.sh
Executable file
@@ -0,0 +1,571 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# pack_offline_bundle_airgap_macos.sh
|
||||||
|
# ============================================================================
|
||||||
|
# Gradle Offline Bundle Packer (macOS)
|
||||||
|
# ============================================================================
|
||||||
|
# Version: 4.0
|
||||||
|
#
|
||||||
|
# WORKFLOW:
|
||||||
|
# 1. [ONLINE] Build project (./gradlew bootJar) - downloads all deps
|
||||||
|
# 2. [ONLINE] Test run (./gradlew bootRun) - verify app works
|
||||||
|
# 3. [OFFLINE TEST] Verify offline build works
|
||||||
|
# 4. Create bundle with all cached dependencies
|
||||||
|
#
|
||||||
|
# REQUIREMENTS:
|
||||||
|
# - Internet connection (for initial build)
|
||||||
|
# - Project with gradlew
|
||||||
|
# - macOS 10.13+ (High Sierra or later)
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Configuration
|
||||||
|
# ============================================================================
|
||||||
|
WRAPPER_SEED_PATH="wrapper_jar_seed"
|
||||||
|
OFFLINE_HOME_NAME="_offline_gradle_home"
|
||||||
|
BOOTRUN_TIMEOUT_SECONDS=60
|
||||||
|
|
||||||
|
# Color codes
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
GRAY='\033[0;90m'
|
||||||
|
WHITE='\033[1;37m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo -e "${CYAN} Gradle Offline Bundle Packer v4.0 (macOS)${NC}"
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${WHITE} This script will:${NC}"
|
||||||
|
echo -e "${GRAY} 1. Build project with internet (download dependencies)${NC}"
|
||||||
|
echo -e "${GRAY} 2. Test run application (verify it works)${NC}"
|
||||||
|
echo -e "${GRAY} 3. Test offline build (verify cache is complete)${NC}"
|
||||||
|
echo -e "${GRAY} 4. Create offline bundle for air-gapped environment${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [1/20] Check Current Directory
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[1/20] Check Current Directory ==${NC}"
|
||||||
|
ROOT="$(pwd)"
|
||||||
|
echo "ROOT_DIR: $ROOT"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [2/20] Check Required Files
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[2/20] Check Required Files ==${NC}"
|
||||||
|
|
||||||
|
if [ ! -f "./gradlew" ]; then
|
||||||
|
echo -e "${RED}ERROR: gradlew not found. Run from project root.${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
chmod +x ./gradlew
|
||||||
|
echo -e "${GREEN}[OK] gradlew${NC}"
|
||||||
|
|
||||||
|
BUILD_FILE=""
|
||||||
|
if [ -f "./build.gradle" ]; then
|
||||||
|
BUILD_FILE="build.gradle"
|
||||||
|
elif [ -f "./build.gradle.kts" ]; then
|
||||||
|
BUILD_FILE="build.gradle.kts"
|
||||||
|
else
|
||||||
|
echo -e "${RED}ERROR: build.gradle(.kts) not found.${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}[OK] $BUILD_FILE${NC}"
|
||||||
|
|
||||||
|
SETTINGS_FILE=""
|
||||||
|
if [ -f "./settings.gradle" ]; then
|
||||||
|
SETTINGS_FILE="settings.gradle"
|
||||||
|
echo -e "${GREEN}[OK] $SETTINGS_FILE${NC}"
|
||||||
|
elif [ -f "./settings.gradle.kts" ]; then
|
||||||
|
SETTINGS_FILE="settings.gradle.kts"
|
||||||
|
echo -e "${GREEN}[OK] $SETTINGS_FILE${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [3/20] Check Gradle Wrapper
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[3/20] Check Gradle Wrapper ==${NC}"
|
||||||
|
|
||||||
|
WRAPPER_DIR="$ROOT/gradle/wrapper"
|
||||||
|
WRAPPER_JAR="$WRAPPER_DIR/gradle-wrapper.jar"
|
||||||
|
WRAPPER_PROP="$WRAPPER_DIR/gradle-wrapper.properties"
|
||||||
|
|
||||||
|
mkdir -p "$WRAPPER_DIR"
|
||||||
|
|
||||||
|
if [ ! -f "$WRAPPER_PROP" ]; then
|
||||||
|
echo -e "${RED}ERROR: gradle-wrapper.properties not found.${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$WRAPPER_JAR" ]; then
|
||||||
|
SEED_JAR="$ROOT/$WRAPPER_SEED_PATH/gradle-wrapper.jar"
|
||||||
|
if [ -f "$SEED_JAR" ]; then
|
||||||
|
cp "$SEED_JAR" "$WRAPPER_JAR"
|
||||||
|
echo -e "${GREEN}[OK] Wrapper jar injected from seed${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}ERROR: gradle-wrapper.jar missing${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}[OK] gradle-wrapper.jar exists${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create seed backup
|
||||||
|
SEED_DIR="$ROOT/$WRAPPER_SEED_PATH"
|
||||||
|
if [ ! -d "$SEED_DIR" ]; then
|
||||||
|
mkdir -p "$SEED_DIR"
|
||||||
|
cp "$WRAPPER_JAR" "$SEED_DIR/gradle-wrapper.jar"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [4/20] Set GRADLE_USER_HOME (Project Local)
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[4/20] Set GRADLE_USER_HOME ==${NC}"
|
||||||
|
|
||||||
|
OFFLINE_HOME="$ROOT/$OFFLINE_HOME_NAME"
|
||||||
|
mkdir -p "$OFFLINE_HOME"
|
||||||
|
export GRADLE_USER_HOME="$OFFLINE_HOME"
|
||||||
|
|
||||||
|
echo -e "${CYAN}GRADLE_USER_HOME = $GRADLE_USER_HOME${NC}"
|
||||||
|
echo -e "${GRAY}[INFO] All dependencies will be cached in project folder${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [5/20] Check Internet Connection
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[5/20] Check Internet Connection ==${NC}"
|
||||||
|
|
||||||
|
HAS_INTERNET=false
|
||||||
|
TEST_HOSTS=("plugins.gradle.org" "repo.maven.apache.org" "repo1.maven.org")
|
||||||
|
|
||||||
|
for TEST_HOST in "${TEST_HOSTS[@]}"; do
|
||||||
|
# macOS ping doesn't have -W, use -t instead
|
||||||
|
if ping -c 1 -t 3 "$TEST_HOST" &>/dev/null; then
|
||||||
|
HAS_INTERNET=true
|
||||||
|
echo -e "${GREEN}[OK] Connected to $TEST_HOST${NC}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$HAS_INTERNET" = false ]; then
|
||||||
|
# Try DNS resolution as fallback
|
||||||
|
if nslookup google.com &>/dev/null || host google.com &>/dev/null; then
|
||||||
|
HAS_INTERNET=true
|
||||||
|
echo -e "${GREEN}[OK] Internet available (DNS)${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$HAS_INTERNET" = false ]; then
|
||||||
|
echo ""
|
||||||
|
echo -e "${RED}============================================================${NC}"
|
||||||
|
echo -e "${RED} ERROR: No Internet Connection!${NC}"
|
||||||
|
echo -e "${RED}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}This script requires internet for initial build.${NC}"
|
||||||
|
echo -e "${YELLOW}Please connect to internet and run again.${NC}"
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [6/20] Initial Gradle Setup
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[6/20] Initial Gradle Setup ==${NC}"
|
||||||
|
echo -e "${GRAY}[INFO] Downloading Gradle distribution...${NC}"
|
||||||
|
|
||||||
|
if ./gradlew --version &>/dev/null; then
|
||||||
|
GRADLE_VERSION=$(./gradlew --version 2>&1 | grep "^Gradle" | awk '{print $2}')
|
||||||
|
echo -e "${GREEN}[OK] Gradle $GRADLE_VERSION${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}[ERROR] Gradle setup failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [7/20] ONLINE BUILD - bootJar (Download All Dependencies)
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[7/20] ONLINE BUILD - bootJar ==${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo -e "${CYAN} ONLINE BUILD (with Internet)${NC}"
|
||||||
|
echo -e "${CYAN} Downloading all dependencies to local cache${NC}"
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
BUILD_SUCCESS=false
|
||||||
|
|
||||||
|
./gradlew clean bootJar --no-daemon
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
BUILD_SUCCESS=true
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}============================================================${NC}"
|
||||||
|
echo -e "${GREEN} ONLINE BUILD SUCCESS!${NC}"
|
||||||
|
echo -e "${GREEN}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ -d "./build/libs" ]; then
|
||||||
|
echo -e "${CYAN}JAR files:${NC}"
|
||||||
|
ls -lh ./build/libs/*.jar 2>/dev/null | awk '{print " " $9 " (" $5 ")"}'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo -e "${RED}============================================================${NC}"
|
||||||
|
echo -e "${RED} BUILD FAILED!${NC}"
|
||||||
|
echo -e "${RED}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Build failed. Cannot continue.${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [8/20] Stop Daemons
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[8/20] Stop Daemons ==${NC}"
|
||||||
|
|
||||||
|
./gradlew --stop &>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
echo -e "${GREEN}[OK] Daemons stopped${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [9/20] ONLINE TEST - bootRun (Verify Application Works)
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[9/20] ONLINE TEST - bootRun ==${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo -e "${CYAN} Testing application startup (timeout: ${BOOTRUN_TIMEOUT_SECONDS}s)${NC}"
|
||||||
|
echo -e "${CYAN} Will automatically stop after successful startup${NC}"
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
BOOTRUN_SUCCESS=false
|
||||||
|
|
||||||
|
# macOS uses gtimeout if available, otherwise perl-based timeout
|
||||||
|
if command -v gtimeout &>/dev/null; then
|
||||||
|
gtimeout ${BOOTRUN_TIMEOUT_SECONDS}s ./gradlew bootRun --no-daemon &
|
||||||
|
else
|
||||||
|
# Fallback: start in background and kill after timeout
|
||||||
|
./gradlew bootRun --no-daemon &
|
||||||
|
fi
|
||||||
|
BOOTRUN_PID=$!
|
||||||
|
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
if ps -p $BOOTRUN_PID &>/dev/null; then
|
||||||
|
BOOTRUN_SUCCESS=true
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}[OK] Application started successfully${NC}"
|
||||||
|
kill $BOOTRUN_PID &>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}[WARN] Application may not have started properly${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup - macOS process cleanup
|
||||||
|
pkill -f "gradle.*bootRun" &>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [10/20] Stop Daemons Again
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[10/20] Stop Daemons Again ==${NC}"
|
||||||
|
|
||||||
|
./gradlew --stop &>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
echo -e "${GREEN}[OK] Daemons stopped${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [11/20] OFFLINE BUILD TEST (Verify Cache Completeness)
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[11/20] OFFLINE BUILD TEST ==${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo -e "${CYAN} OFFLINE BUILD TEST (--offline flag)${NC}"
|
||||||
|
echo -e "${CYAN} Verifying all dependencies are cached${NC}"
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
OFFLINE_SUCCESS=false
|
||||||
|
|
||||||
|
./gradlew clean bootJar --offline --no-daemon
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
OFFLINE_SUCCESS=true
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}============================================================${NC}"
|
||||||
|
echo -e "${GREEN} OFFLINE BUILD TEST PASSED!${NC}"
|
||||||
|
echo -e "${GREEN}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}[OK] All dependencies are cached${NC}"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo -e "${RED}============================================================${NC}"
|
||||||
|
echo -e "${RED} OFFLINE BUILD TEST FAILED!${NC}"
|
||||||
|
echo -e "${RED}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Some dependencies may be missing from cache.${NC}"
|
||||||
|
echo -e "${YELLOW}The bundle may not work in air-gapped environment.${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Continue anyway? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [12/20] Stop Daemons Before Archive
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[12/20] Stop Daemons Before Archive ==${NC}"
|
||||||
|
|
||||||
|
./gradlew --stop &>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
echo -e "${GREEN}[OK] Daemons stopped${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [13/20] Verify settings.gradle for Offline
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[13/20] Verify settings.gradle ==${NC}"
|
||||||
|
|
||||||
|
if [ -n "$SETTINGS_FILE" ]; then
|
||||||
|
if grep -q "mavenLocal()" "$SETTINGS_FILE" && grep -q "pluginManagement" "$SETTINGS_FILE"; then
|
||||||
|
echo -e "${GREEN}[OK] settings.gradle configured for offline${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}[WARN] settings.gradle may need offline configuration${NC}"
|
||||||
|
echo -e "${GRAY}[INFO] Consider adding mavenLocal() to pluginManagement and repositories${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${GRAY}[INFO] No settings.gradle found${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [14/20] Create Helper Scripts
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[14/20] Create Helper Scripts ==${NC}"
|
||||||
|
|
||||||
|
# run_offline_build.sh
|
||||||
|
cat > "$ROOT/run_offline_build.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# run_offline_build.sh - Build JAR offline
|
||||||
|
export GRADLE_USER_HOME="$(pwd)/_offline_gradle_home"
|
||||||
|
echo "GRADLE_USER_HOME = $GRADLE_USER_HOME"
|
||||||
|
echo ""
|
||||||
|
./gradlew --offline bootJar --no-daemon
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "BUILD SUCCESS!"
|
||||||
|
echo ""
|
||||||
|
echo "JAR files:"
|
||||||
|
ls -lh ./build/libs/*.jar 2>/dev/null | awk '{print " " $9}'
|
||||||
|
else
|
||||||
|
echo "BUILD FAILED"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
chmod +x "$ROOT/run_offline_build.sh"
|
||||||
|
echo -e "${GREEN}[OK] run_offline_build.sh${NC}"
|
||||||
|
|
||||||
|
# run_offline_bootrun.sh
|
||||||
|
cat > "$ROOT/run_offline_bootrun.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# run_offline_bootrun.sh - Run application offline
|
||||||
|
export GRADLE_USER_HOME="$(pwd)/_offline_gradle_home"
|
||||||
|
echo "GRADLE_USER_HOME = $GRADLE_USER_HOME"
|
||||||
|
echo ""
|
||||||
|
echo "Starting application (Ctrl+C to stop)..."
|
||||||
|
echo ""
|
||||||
|
./gradlew --offline bootRun --no-daemon
|
||||||
|
EOF
|
||||||
|
chmod +x "$ROOT/run_offline_bootrun.sh"
|
||||||
|
echo -e "${GREEN}[OK] run_offline_bootrun.sh${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [15/20] Final Daemon Cleanup
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[15/20] Final Daemon Cleanup ==${NC}"
|
||||||
|
|
||||||
|
./gradlew --stop &>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
echo -e "${GREEN}[OK] Daemons stopped${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [16/20] Clean Lock Files
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[16/20] Clean Lock Files ==${NC}"
|
||||||
|
|
||||||
|
DAEMON_DIR="$OFFLINE_HOME/daemon"
|
||||||
|
if [ -d "$DAEMON_DIR" ]; then
|
||||||
|
rm -rf "$DAEMON_DIR" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
find "$OFFLINE_HOME" -type f \( -name "*.lock" -o -name "*.log" -o -name "*.tmp" \) -delete 2>/dev/null || true
|
||||||
|
|
||||||
|
echo -e "${GREEN}[OK] Lock files cleaned${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [17/20] Calculate Cache Size
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[17/20] Cache Summary ==${NC}"
|
||||||
|
|
||||||
|
CACHES_DIR="$OFFLINE_HOME/caches"
|
||||||
|
WRAPPER_DISTS="$OFFLINE_HOME/wrapper/dists"
|
||||||
|
|
||||||
|
TOTAL_SIZE=0
|
||||||
|
|
||||||
|
if [ -d "$CACHES_DIR" ]; then
|
||||||
|
# macOS uses different options for du
|
||||||
|
if du -k "$CACHES_DIR" &>/dev/null; then
|
||||||
|
SIZE=$(du -sk "$CACHES_DIR" 2>/dev/null | cut -f1)
|
||||||
|
SIZE=$((SIZE * 1024)) # Convert to bytes
|
||||||
|
else
|
||||||
|
SIZE=0
|
||||||
|
fi
|
||||||
|
TOTAL_SIZE=$((TOTAL_SIZE + SIZE))
|
||||||
|
SIZE_MB=$(awk "BEGIN {printf \"%.2f\", $SIZE / 1048576}")
|
||||||
|
echo -e "${CYAN}[INFO] Dependencies: ${SIZE_MB} MB${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$WRAPPER_DISTS" ]; then
|
||||||
|
if du -k "$WRAPPER_DISTS" &>/dev/null; then
|
||||||
|
SIZE=$(du -sk "$WRAPPER_DISTS" 2>/dev/null | cut -f1)
|
||||||
|
SIZE=$((SIZE * 1024))
|
||||||
|
else
|
||||||
|
SIZE=0
|
||||||
|
fi
|
||||||
|
TOTAL_SIZE=$((TOTAL_SIZE + SIZE))
|
||||||
|
SIZE_MB=$(awk "BEGIN {printf \"%.2f\", $SIZE / 1048576}")
|
||||||
|
echo -e "${CYAN}[INFO] Gradle dist: ${SIZE_MB} MB${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOTAL_MB=$(awk "BEGIN {printf \"%.2f\", $TOTAL_SIZE / 1048576}")
|
||||||
|
echo -e "${CYAN}[INFO] Total cache: ${TOTAL_MB} MB${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [18/20] Create Archive
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[18/20] Create Archive ==${NC}"
|
||||||
|
|
||||||
|
BASE_NAME=$(basename "$ROOT")
|
||||||
|
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||||
|
PARENT=$(dirname "$ROOT")
|
||||||
|
ARCHIVE_PATH="${PARENT}/${BASE_NAME}_offline_bundle_${TIMESTAMP}.tar.gz"
|
||||||
|
|
||||||
|
echo "Archive: $ARCHIVE_PATH"
|
||||||
|
echo -e "${GRAY}[INFO] Creating archive (this may take several minutes)...${NC}"
|
||||||
|
|
||||||
|
# macOS tar with BSD options
|
||||||
|
tar -czf "$ARCHIVE_PATH" \
|
||||||
|
--exclude=".git" \
|
||||||
|
--exclude=".idea" \
|
||||||
|
--exclude=".DS_Store" \
|
||||||
|
--exclude="*.log" \
|
||||||
|
--exclude="*.lock" \
|
||||||
|
--exclude="_offline_gradle_home/daemon" \
|
||||||
|
--exclude="_offline_gradle_home/native" \
|
||||||
|
--exclude="_offline_gradle_home/jdks" \
|
||||||
|
--exclude="build" \
|
||||||
|
--exclude="out" \
|
||||||
|
--exclude=".gradle" \
|
||||||
|
-C "$ROOT" .
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "${RED}ERROR: tar failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# macOS stat command
|
||||||
|
ARCHIVE_SIZE=$(stat -f%z "$ARCHIVE_PATH" 2>/dev/null)
|
||||||
|
ARCHIVE_SIZE_MB=$(awk "BEGIN {printf \"%.2f\", $ARCHIVE_SIZE / 1048576}")
|
||||||
|
echo -e "${GREEN}[OK] Archive created: ${ARCHIVE_SIZE_MB} MB${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [19/20] Verify Archive
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[19/20] Verify Archive ==${NC}"
|
||||||
|
|
||||||
|
CHECKS=(
|
||||||
|
"gradle/wrapper/gradle-wrapper.jar"
|
||||||
|
"gradlew"
|
||||||
|
"_offline_gradle_home/caches"
|
||||||
|
"run_offline_build.sh"
|
||||||
|
)
|
||||||
|
|
||||||
|
for CHECK in "${CHECKS[@]}"; do
|
||||||
|
if tar -tzf "$ARCHIVE_PATH" | grep -q "$CHECK"; then
|
||||||
|
echo -e " ${GREEN}[OK] $CHECK${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${YELLOW}[WARN] $CHECK${NC}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [20/20] Complete
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${GREEN}============================================================${NC}"
|
||||||
|
echo -e "${GREEN} BUNDLE CREATION COMPLETE!${NC}"
|
||||||
|
echo -e "${GREEN}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}Archive: $ARCHIVE_PATH${NC}"
|
||||||
|
echo -e "${CYAN}Size: ${ARCHIVE_SIZE_MB} MB${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo -e "${CYAN} Test Results${NC}"
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
if [ "$BUILD_SUCCESS" = true ]; then
|
||||||
|
echo -e " Online build (bootJar): ${GREEN}PASSED${NC}"
|
||||||
|
else
|
||||||
|
echo -e " Online build (bootJar): ${RED}FAILED${NC}"
|
||||||
|
fi
|
||||||
|
if [ "$BOOTRUN_SUCCESS" = true ]; then
|
||||||
|
echo -e " Online test (bootRun): ${GREEN}PASSED${NC}"
|
||||||
|
else
|
||||||
|
echo -e " Online test (bootRun): ${YELLOW}SKIPPED${NC}"
|
||||||
|
fi
|
||||||
|
if [ "$OFFLINE_SUCCESS" = true ]; then
|
||||||
|
echo -e " Offline build test: ${GREEN}PASSED${NC}"
|
||||||
|
else
|
||||||
|
echo -e " Offline build test: ${RED}FAILED${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${YELLOW}============================================================${NC}"
|
||||||
|
echo -e "${YELLOW} Usage in Air-gapped Environment${NC}"
|
||||||
|
echo -e "${YELLOW}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${WHITE}Option 1: Use unpack script${NC}"
|
||||||
|
echo -e "${GRAY} ./unpack_and_offline_build_airgap.sh${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${WHITE}Option 2: Manual extraction${NC}"
|
||||||
|
echo -e "${GRAY} tar -xzf <archive>.tar.gz${NC}"
|
||||||
|
echo -e "${GRAY} cd <project>${NC}"
|
||||||
|
echo -e "${GRAY} ./run_offline_build.sh${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${WHITE}Option 3: Direct commands${NC}"
|
||||||
|
echo -e "${GRAY} export GRADLE_USER_HOME=\"./_offline_gradle_home\"${NC}"
|
||||||
|
echo -e "${GRAY} ./gradlew --offline bootJar --no-daemon${NC}"
|
||||||
|
echo ""
|
||||||
359
gradle/mac/unpack_and_offline_build_airgap_macos.sh
Executable file
359
gradle/mac/unpack_and_offline_build_airgap_macos.sh
Executable file
@@ -0,0 +1,359 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# unpack_and_offline_build_airgap_macos.sh
|
||||||
|
# ============================================================================
|
||||||
|
# Execution Environment: OFFLINE (Air-gapped, No Internet)
|
||||||
|
# Purpose: Extract bundle and run offline build
|
||||||
|
# ============================================================================
|
||||||
|
# macOS Bash Script
|
||||||
|
# Version: 3.1
|
||||||
|
#
|
||||||
|
# IMPORTANT: This script automatically:
|
||||||
|
# 1. Extracts the archive
|
||||||
|
# 2. Sets GRADLE_USER_HOME to project local cache
|
||||||
|
# 3. Configures settings.gradle for offline resolution
|
||||||
|
# 4. Runs build with --offline flag
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Configuration
|
||||||
|
# ============================================================================
|
||||||
|
WRAPPER_SEED_PATH="wrapper_jar_seed"
|
||||||
|
OFFLINE_HOME_NAME="_offline_gradle_home"
|
||||||
|
|
||||||
|
# Color codes
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
GRAY='\033[0;90m'
|
||||||
|
WHITE='\033[1;37m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo -e "${CYAN} Gradle Offline Build Runner (macOS)${NC}"
|
||||||
|
echo -e "${CYAN} Environment: AIR-GAPPED (No Internet)${NC}"
|
||||||
|
echo -e "${CYAN} Mode: Fully Offline (--offline enforced)${NC}"
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [1/16] Check Current Directory
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[1/16] Check Current Directory ==${NC}"
|
||||||
|
START_DIR="$(pwd)"
|
||||||
|
echo "PWD: $START_DIR"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [2/16] Select Archive
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[2/16] Select Archive ==${NC}"
|
||||||
|
|
||||||
|
ARCHIVE=""
|
||||||
|
if [ $# -ge 1 ]; then
|
||||||
|
ARCHIVE="$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$ARCHIVE" ]; then
|
||||||
|
# Auto-detect most recent .tar.gz file (macOS compatible)
|
||||||
|
ARCHIVE=$(find "$START_DIR" -maxdepth 1 -type f \( -name "*.tar.gz" -o -name "*.tgz" \) -exec stat -f "%m %N" {} \; 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)
|
||||||
|
|
||||||
|
if [ -z "$ARCHIVE" ]; then
|
||||||
|
echo -e "${RED}[ERROR] No archive found${NC}"
|
||||||
|
ls -lh "$START_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${CYAN}[AUTO] $(basename "$ARCHIVE")${NC}"
|
||||||
|
else
|
||||||
|
if [ ! -f "$ARCHIVE" ]; then
|
||||||
|
ARCHIVE="$START_DIR/$ARCHIVE"
|
||||||
|
fi
|
||||||
|
echo -e "${CYAN}[USER] $(basename "$ARCHIVE")${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$ARCHIVE" ]; then
|
||||||
|
echo -e "${RED}ERROR: Archive not found: $ARCHIVE${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# macOS stat command
|
||||||
|
ARCHIVE_SIZE=$(stat -f%z "$ARCHIVE" 2>/dev/null)
|
||||||
|
ARCHIVE_SIZE_MB=$(awk "BEGIN {printf \"%.2f\", $ARCHIVE_SIZE / 1048576}")
|
||||||
|
echo "Size: ${ARCHIVE_SIZE_MB} MB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [3/16] Check tar
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[3/16] Check tar ==${NC}"
|
||||||
|
|
||||||
|
if ! command -v tar &>/dev/null; then
|
||||||
|
echo -e "${RED}ERROR: tar not found${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}[OK] tar found${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [4/16] Extract Archive
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[4/16] Extract Archive ==${NC}"
|
||||||
|
echo -e "${GRAY}[INFO] Extracting...${NC}"
|
||||||
|
|
||||||
|
tar -xzf "$ARCHIVE" -C "$START_DIR"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "${RED}ERROR: Extraction failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}[OK] Extracted${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [5/16] Set Permissions
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[5/16] Set Permissions ==${NC}"
|
||||||
|
|
||||||
|
chmod -R u+rw "$START_DIR" 2>/dev/null || true
|
||||||
|
# Remove extended attributes that macOS may add
|
||||||
|
xattr -cr "$START_DIR" 2>/dev/null || true
|
||||||
|
echo -e "${GREEN}[OK] Permissions set${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [6/16] Find Project Root
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[6/16] Find Project Root ==${NC}"
|
||||||
|
|
||||||
|
GRADLEW=$(find "$START_DIR" -name "gradlew" -type f 2>/dev/null | sort | head -1)
|
||||||
|
if [ -z "$GRADLEW" ]; then
|
||||||
|
echo -e "${RED}ERROR: gradlew not found${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PROJECT_DIR=$(dirname "$GRADLEW")
|
||||||
|
echo -e "${CYAN}Project: $PROJECT_DIR${NC}"
|
||||||
|
cd "$PROJECT_DIR"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [7/16] Fix Permissions
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[7/16] Fix Permissions ==${NC}"
|
||||||
|
|
||||||
|
chmod +x ./gradlew
|
||||||
|
find . -name "*.sh" -type f -exec chmod +x {} \; 2>/dev/null || true
|
||||||
|
# Remove quarantine attributes that macOS adds to downloaded files
|
||||||
|
xattr -d com.apple.quarantine ./gradlew 2>/dev/null || true
|
||||||
|
find . -name "*.jar" -exec xattr -d com.apple.quarantine {} \; 2>/dev/null || true
|
||||||
|
echo -e "${GREEN}[OK] Permissions fixed${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [8/16] Verify Wrapper
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[8/16] Verify Wrapper ==${NC}"
|
||||||
|
|
||||||
|
WRAPPER_DIR="$PROJECT_DIR/gradle/wrapper"
|
||||||
|
WRAPPER_JAR="$WRAPPER_DIR/gradle-wrapper.jar"
|
||||||
|
WRAPPER_PROP="$WRAPPER_DIR/gradle-wrapper.properties"
|
||||||
|
|
||||||
|
if [ ! -f "$WRAPPER_PROP" ]; then
|
||||||
|
echo -e "${RED}ERROR: gradle-wrapper.properties missing${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$WRAPPER_JAR" ]; then
|
||||||
|
SEED_JAR="$PROJECT_DIR/$WRAPPER_SEED_PATH/gradle-wrapper.jar"
|
||||||
|
if [ -f "$SEED_JAR" ]; then
|
||||||
|
mkdir -p "$WRAPPER_DIR"
|
||||||
|
cp "$SEED_JAR" "$WRAPPER_JAR"
|
||||||
|
echo -e "${GREEN}[OK] Injected from seed${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}ERROR: wrapper jar missing${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}[OK] Wrapper verified${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [9/16] Set GRADLE_USER_HOME
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[9/16] Set GRADLE_USER_HOME ==${NC}"
|
||||||
|
|
||||||
|
OFFLINE_HOME="$PROJECT_DIR/$OFFLINE_HOME_NAME"
|
||||||
|
if [ ! -d "$OFFLINE_HOME" ]; then
|
||||||
|
echo -e "${RED}ERROR: _offline_gradle_home not found in archive${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export GRADLE_USER_HOME="$OFFLINE_HOME"
|
||||||
|
echo -e "${CYAN}GRADLE_USER_HOME = $GRADLE_USER_HOME${NC}"
|
||||||
|
|
||||||
|
# Check cache
|
||||||
|
CACHES_DIR="$OFFLINE_HOME/caches"
|
||||||
|
if [ -d "$CACHES_DIR" ]; then
|
||||||
|
# macOS du command
|
||||||
|
if du -k "$CACHES_DIR" &>/dev/null; then
|
||||||
|
CACHE_SIZE=$(du -sk "$CACHES_DIR" 2>/dev/null | cut -f1)
|
||||||
|
CACHE_SIZE=$((CACHE_SIZE * 1024))
|
||||||
|
else
|
||||||
|
CACHE_SIZE=0
|
||||||
|
fi
|
||||||
|
CACHE_SIZE_MB=$(awk "BEGIN {printf \"%.2f\", $CACHE_SIZE / 1048576}")
|
||||||
|
echo -e "${CYAN}[INFO] Cache size: ${CACHE_SIZE_MB} MB${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}[WARN] No cache folder found${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [10/16] Verify settings.gradle
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[10/16] Verify settings.gradle ==${NC}"
|
||||||
|
|
||||||
|
SETTINGS_FILE=""
|
||||||
|
if [ -f "./settings.gradle" ]; then
|
||||||
|
SETTINGS_FILE="settings.gradle"
|
||||||
|
elif [ -f "./settings.gradle.kts" ]; then
|
||||||
|
SETTINGS_FILE="settings.gradle.kts"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$SETTINGS_FILE" ]; then
|
||||||
|
if grep -q "mavenLocal()" "$SETTINGS_FILE" && grep -q "pluginManagement" "$SETTINGS_FILE"; then
|
||||||
|
echo -e "${GREEN}[OK] settings.gradle configured for offline${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}[WARN] settings.gradle may not be configured for offline${NC}"
|
||||||
|
echo -e "${GRAY}[INFO] Build may fail if plugins not cached${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [11/16] Test Gradle
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[11/16] Test Gradle ==${NC}"
|
||||||
|
|
||||||
|
GRADLE_WORKS=false
|
||||||
|
if ./gradlew --offline --version &>/dev/null; then
|
||||||
|
GRADLE_WORKS=true
|
||||||
|
echo -e "${GREEN}[OK] Gradle working in offline mode${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}[WARN] Gradle --version failed${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [12/16] Stop Daemon
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[12/16] Stop Daemon ==${NC}"
|
||||||
|
|
||||||
|
./gradlew --stop &>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
echo -e "${GREEN}[OK] Daemon stopped${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [13/16] Run Offline Build
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[13/16] Run Offline Build ==${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo -e "${CYAN} Building with --offline flag${NC}"
|
||||||
|
echo -e "${CYAN} All dependencies from local cache${NC}"
|
||||||
|
echo -e "${CYAN}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
BUILD_SUCCESS=false
|
||||||
|
BUILD_TASK=""
|
||||||
|
|
||||||
|
# Try bootJar
|
||||||
|
echo -e "${GRAY}[TRY] --offline bootJar...${NC}"
|
||||||
|
if ./gradlew --offline clean bootJar --no-daemon; then
|
||||||
|
BUILD_SUCCESS=true
|
||||||
|
BUILD_TASK="bootJar"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try jar
|
||||||
|
if [ "$BUILD_SUCCESS" = false ]; then
|
||||||
|
echo -e "${GRAY}[TRY] --offline jar...${NC}"
|
||||||
|
if ./gradlew --offline clean jar --no-daemon; then
|
||||||
|
BUILD_SUCCESS=true
|
||||||
|
BUILD_TASK="jar"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try build
|
||||||
|
if [ "$BUILD_SUCCESS" = false ]; then
|
||||||
|
echo -e "${GRAY}[TRY] --offline build...${NC}"
|
||||||
|
if ./gradlew --offline build --no-daemon; then
|
||||||
|
BUILD_SUCCESS=true
|
||||||
|
BUILD_TASK="build"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
if [ "$BUILD_SUCCESS" = true ]; then
|
||||||
|
echo -e "${GREEN}============================================================${NC}"
|
||||||
|
echo -e "${GREEN} BUILD SUCCESS! (task: $BUILD_TASK)${NC}"
|
||||||
|
echo -e "${GREEN}============================================================${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}============================================================${NC}"
|
||||||
|
echo -e "${RED} BUILD FAILED!${NC}"
|
||||||
|
echo -e "${RED}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Possible causes:${NC}"
|
||||||
|
echo -e "${WHITE} - Dependencies not in cache${NC}"
|
||||||
|
echo -e "${WHITE} - Plugin resolution failed${NC}"
|
||||||
|
echo -e "${WHITE} - Need complete build in online env first${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [14/16] Show Build Output
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[14/16] Build Output ==${NC}"
|
||||||
|
|
||||||
|
LIBS_DIR="$PROJECT_DIR/build/libs"
|
||||||
|
if [ -d "$LIBS_DIR" ]; then
|
||||||
|
echo -e "${CYAN}build/libs contents:${NC}"
|
||||||
|
ls -lh "$LIBS_DIR"/*.jar 2>/dev/null | awk '{printf " %-40s %10s\n", $9, $5}'
|
||||||
|
|
||||||
|
MAIN_JAR=$(find "$LIBS_DIR" -name "*.jar" -type f ! -name "*-plain.jar" ! -name "*-sources.jar" ! -name "*-javadoc.jar" 2>/dev/null | head -1)
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}[WARN] build/libs not found${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [15/16] Run Instructions
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${YELLOW}==[15/16] Run Instructions ==${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ -n "$MAIN_JAR" ]; then
|
||||||
|
echo -e "${CYAN}To run the application:${NC}"
|
||||||
|
echo -e "${WHITE} java -jar $(basename "$MAIN_JAR")${NC}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${CYAN}To rebuild:${NC}"
|
||||||
|
echo -e "${WHITE} export GRADLE_USER_HOME=\"./_offline_gradle_home\"${NC}"
|
||||||
|
echo -e "${WHITE} ./gradlew --offline bootJar --no-daemon${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# [16/16] Complete
|
||||||
|
# ============================================================================
|
||||||
|
echo -e "${GREEN}============================================================${NC}"
|
||||||
|
echo -e "${GREEN} Offline Build Complete!${NC}"
|
||||||
|
echo -e "${GREEN}============================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}Project: $PROJECT_DIR${NC}"
|
||||||
|
echo ""
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.dto;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
|
|
||||||
public class ChngDetectMastDto {
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public static class Basic {
|
|
||||||
|
|
||||||
private String chnDtctMstId; // 탐지마스터아이디
|
|
||||||
private String cprsYr; // 비교년도 2023
|
|
||||||
private String crtrYr; // 기준년도 2024
|
|
||||||
private String chnDtctSno; // 차수 (1 | 2 | ...)
|
|
||||||
private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
|
||||||
private String chnDtctCnt; // 탐지객체개수
|
|
||||||
private String pnuMpngCnt; // PNU매핑개수
|
|
||||||
private String lrmYmd; // 지적도일자
|
|
||||||
private String pathNm; // 탐지결과 절대경로명 /kamco_nas/export/{chnDtctId}
|
|
||||||
private List<ChnDetectMastExcnStepDto> excnList; // 등록진행상태히스토리 (최근것부터 DESC)
|
|
||||||
private String excnStepCd; // 실행단계코드
|
|
||||||
private String excnStep; // 실행단계코드에 해당하는 영문명
|
|
||||||
private String excnPgrt; // 실행단계진행율
|
|
||||||
private String excnBngnDt; // 실행단계시작시간
|
|
||||||
private String excnEndDt; // 실행단계종료시간
|
|
||||||
private String rmk; // 비고
|
|
||||||
private String crtDt; // 생성일시
|
|
||||||
private String crtEpno; // 생성사원번호
|
|
||||||
private String crtIp; // 생성사원아이피
|
|
||||||
private String chgDt; // 변경일시
|
|
||||||
private String chgEpno; // 변경사원번호
|
|
||||||
private String chgIp; // 변경사원아이피
|
|
||||||
private String delYn; // 삭제여부
|
|
||||||
//
|
|
||||||
private String reqEpno; // 요청사원번호
|
|
||||||
private String reqIp; // 요청사원어이피
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public static class ChnDetectMastExcnStepDto {
|
|
||||||
|
|
||||||
private String srno; // 일련번호
|
|
||||||
private String chnDtctMstId; // 탐지마스터아이디
|
|
||||||
private String excnStepCd; // 실행단계코드
|
|
||||||
private String excnStep; // 실행단계코드에 해당하는 영문명
|
|
||||||
private String excnPgrt; // 실행단계진행율
|
|
||||||
private String excnEndDt; // 실행단계종료시간
|
|
||||||
private String errCd; // 오류코드
|
|
||||||
private String errMsg; // 오류메세지
|
|
||||||
private String crtDt; // 실행단계시작시간
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public static class ChnDetectMastReqDto {
|
|
||||||
private String cprsYr; // 비교년도 2023
|
|
||||||
private String crtrYr; // 기준년도 2024
|
|
||||||
private String chnDtctSno; // 차수 (1 | 2 | ...)
|
|
||||||
private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
|
||||||
private String pathNm; // 탐지결과 절대경로명 /kamco_nas/export/{chnDtctId}
|
|
||||||
private String reqEpno; // 사원번호
|
|
||||||
private String reqIp; // 사원아이피
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public static class ChnDetectContDto {
|
|
||||||
|
|
||||||
private String chnDtctMstId; // 탐지콘텐츠아이디
|
|
||||||
private String chnDtctContId; // 탐지마스타아이디
|
|
||||||
private String cprsYr; // 비교년도 2023
|
|
||||||
private String crtrYr; // 기준년도 2024
|
|
||||||
private String chnDtctSno; // 차수 (1 | 2 | ...)
|
|
||||||
private String mpqdNo; // 도엽번호
|
|
||||||
private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
|
||||||
private String chnDtctObjtId; // 탐지객체아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
|
||||||
private String chnDtctPolygon; // 탐지객체폴리곤
|
|
||||||
private String chnDtctSqms; // 탐지객체면적
|
|
||||||
private String chnCd; // 변화코드
|
|
||||||
private String chnDtctJson; // 변화탐지JSON
|
|
||||||
private String chnDtctProb; // 변화탐지정확도
|
|
||||||
private String bfClsCd; // 이전부류코드
|
|
||||||
private String bfClsProb; // 이전분류정확도
|
|
||||||
private String afClsCd; // 이후분류코드
|
|
||||||
private String afClsProb; // 이후분류정확도
|
|
||||||
private String crtDt; // 생성일시
|
|
||||||
private String crtEpno; // 생성사원번호
|
|
||||||
private String crtIp; // 생성사원아이피
|
|
||||||
private String delYn; // 삭제여부
|
|
||||||
//
|
|
||||||
private String reqEpno; // 요청사원번호
|
|
||||||
private String reqIp; // 요청사원아이피
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public static class ChnDetectContReqDto {
|
|
||||||
|
|
||||||
private String cprsYr; // 비교년도 2023
|
|
||||||
private String crtrYr; // 기준년도 2024
|
|
||||||
private String chnDtctSno; // 차수 (1 | 2 | ...)
|
|
||||||
private String mpqdNo; // 도엽번호
|
|
||||||
private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
|
||||||
private String chnDtctObjtId; // 탐지객체아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
|
||||||
private String reqEpno; // 사원번호
|
|
||||||
private String reqIp;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public static class ChngDetectMastSearchDto {
|
|
||||||
private String chnDtctId;
|
|
||||||
private String cprsYr;
|
|
||||||
private String crtrYr;
|
|
||||||
private String chnDtctSno;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Schema(name = "ResReturn", description = "수행 후 리턴")
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public static class ResReturn {
|
|
||||||
|
|
||||||
private String flag;
|
|
||||||
private String message;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.postgres.core;
|
|
||||||
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.Basic;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastReq;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.postgres.entity.DetectMastEntity;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.postgres.repository.DetectMastRepository;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class DetectMastCoreService {
|
|
||||||
|
|
||||||
private final DetectMastRepository detectMastRepository;
|
|
||||||
|
|
||||||
public void saveDetectMast(DetectMastReq detectMast) {
|
|
||||||
DetectMastEntity detectMastEntity = new DetectMastEntity();
|
|
||||||
detectMastEntity.setCprsBfYr(detectMast.getCprsBfYr());
|
|
||||||
detectMastEntity.setCprsAdYr(detectMast.getCprsAdYr());
|
|
||||||
detectMastEntity.setDtctSno(detectMast.getDtctSno());
|
|
||||||
detectMastEntity.setPathNm(detectMast.getPathNm());
|
|
||||||
detectMastEntity.setCrtEpno(detectMast.getCrtEpno());
|
|
||||||
detectMastEntity.setCrtIp(detectMast.getCrtIp());
|
|
||||||
detectMastRepository.save(detectMastEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Basic> selectDetectMast(DetectMastSearch detectMast) {
|
|
||||||
return detectMastRepository.findDetectMastList(detectMast).stream()
|
|
||||||
.map(
|
|
||||||
e ->
|
|
||||||
new DetectMastDto.Basic(
|
|
||||||
e.getId(),
|
|
||||||
e.getCprsBfYr(),
|
|
||||||
e.getCprsAdYr(),
|
|
||||||
e.getDtctSno(),
|
|
||||||
e.getPathNm(),
|
|
||||||
e.getCrtEpno(),
|
|
||||||
e.getCrtIp()))
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Basic selectDetectMast(Long id) {
|
|
||||||
DetectMastEntity e =
|
|
||||||
detectMastRepository.findById(id).orElseThrow(() -> new RuntimeException("등록 데이터가 없습니다."));
|
|
||||||
return new DetectMastDto.Basic(
|
|
||||||
e.getId(),
|
|
||||||
e.getCprsBfYr(),
|
|
||||||
e.getCprsAdYr(),
|
|
||||||
e.getDtctSno(),
|
|
||||||
e.getPathNm(),
|
|
||||||
e.getCrtEpno(),
|
|
||||||
e.getCrtIp());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String findPnuData(DetectMastSearch detectMast) {
|
|
||||||
DetectMastEntity detectMastEntity = detectMastRepository.findPnuData(detectMast);
|
|
||||||
return detectMastEntity.getPathNm();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer updatePnu(List<FeaturePnuDto> list) {
|
|
||||||
return detectMastRepository.updateGeomPnu(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.postgres.entity;
|
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.SequenceGenerator;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import jakarta.validation.constraints.Size;
|
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
import java.util.UUID;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.hibernate.annotations.ColumnDefault;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Entity
|
|
||||||
@Table(name = "detect_mast")
|
|
||||||
public class DetectMastEntity {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "detect_mast_id_gen")
|
|
||||||
@SequenceGenerator(
|
|
||||||
name = "detect_mast_id_gen",
|
|
||||||
sequenceName = "seq_detect_mast_id",
|
|
||||||
allocationSize = 1)
|
|
||||||
@Column(name = "dtct_mst_id", nullable = false)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@ColumnDefault("gen_random_uuid()")
|
|
||||||
@Column(name = "dtct_mst_uuid", nullable = false)
|
|
||||||
private UUID dtctMstUuid = UUID.randomUUID();
|
|
||||||
|
|
||||||
@Size(max = 4)
|
|
||||||
@NotNull
|
|
||||||
@Column(name = "cprs_bf_yr", nullable = false, length = 4)
|
|
||||||
private String cprsBfYr;
|
|
||||||
|
|
||||||
@Size(max = 4)
|
|
||||||
@NotNull
|
|
||||||
@Column(name = "cprs_ad_yr", nullable = false, length = 4)
|
|
||||||
private String cprsAdYr;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Column(name = "dtct_sno", nullable = false)
|
|
||||||
private Integer dtctSno;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Column(name = "path_nm", nullable = false, length = Integer.MAX_VALUE)
|
|
||||||
private String pathNm;
|
|
||||||
|
|
||||||
@Size(max = 50)
|
|
||||||
@Column(name = "feature_id", length = 50)
|
|
||||||
private String featureId;
|
|
||||||
|
|
||||||
@Size(max = 30)
|
|
||||||
@NotNull
|
|
||||||
@Column(name = "crt_epno", nullable = false, length = 30)
|
|
||||||
private String crtEpno;
|
|
||||||
|
|
||||||
@Size(max = 45)
|
|
||||||
@NotNull
|
|
||||||
@Column(name = "crt_ip", nullable = false, length = 45)
|
|
||||||
private String crtIp;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@ColumnDefault("now()")
|
|
||||||
@Column(name = "crt_dttm", nullable = false)
|
|
||||||
private ZonedDateTime crtDttm = ZonedDateTime.now();
|
|
||||||
|
|
||||||
@Size(max = 30)
|
|
||||||
@Column(name = "chg_epno", length = 30)
|
|
||||||
private String chgEpno;
|
|
||||||
|
|
||||||
@Size(max = 45)
|
|
||||||
@Column(name = "chg_ip", length = 45)
|
|
||||||
private String chgIp;
|
|
||||||
|
|
||||||
@Column(name = "chg_dttm")
|
|
||||||
private ZonedDateTime chgDttm;
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.postgres.entity;
|
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.SequenceGenerator;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import jakarta.validation.constraints.Size;
|
|
||||||
import java.util.UUID;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.hibernate.annotations.ColumnDefault;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Entity
|
|
||||||
@Table(name = "detect_mast_pnu")
|
|
||||||
public class DetectMastPnuEntity {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "detect_mast_pnu_id_gen")
|
|
||||||
@SequenceGenerator(
|
|
||||||
name = "detect_mast_pnu_id_gen",
|
|
||||||
sequenceName = "seq_detect_mast_pnu_id",
|
|
||||||
allocationSize = 1)
|
|
||||||
@Column(name = "dtct_mst_pnu_id", nullable = false)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@ColumnDefault("gen_random_uuid()")
|
|
||||||
@Column(name = "detect_mast_pnu_uuid", nullable = false)
|
|
||||||
private UUID detectMastPnuUuid;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Column(name = "dtct_mst_id", nullable = false)
|
|
||||||
private Long dtctMstId;
|
|
||||||
|
|
||||||
@Size(max = 4)
|
|
||||||
@NotNull
|
|
||||||
@Column(name = "pnu", nullable = false, length = 4)
|
|
||||||
private String pnu;
|
|
||||||
|
|
||||||
@Column(name = "polygon", length = Integer.MAX_VALUE)
|
|
||||||
private String polygon;
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.postgres.repository;
|
|
||||||
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.postgres.entity.DetectMastPnuEntity;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
|
|
||||||
public interface DetectMastPnuRepository
|
|
||||||
extends JpaRepository<DetectMastPnuEntity, Long>, DetectMastPnuRepositoryCustom {}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.postgres.repository;
|
|
||||||
|
|
||||||
public interface DetectMastPnuRepositoryCustom {}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.postgres.repository;
|
|
||||||
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.postgres.entity.DetectMastEntity;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
|
|
||||||
public interface DetectMastRepository
|
|
||||||
extends JpaRepository<DetectMastEntity, Long>, DetectMastRepositoryCustom {}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.postgres.repository;
|
|
||||||
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.postgres.entity.DetectMastEntity;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface DetectMastRepositoryCustom {
|
|
||||||
|
|
||||||
public List<DetectMastEntity> findDetectMastList(DetectMastSearch detectMast);
|
|
||||||
|
|
||||||
public DetectMastEntity findPnuData(DetectMastSearch detectMast);
|
|
||||||
|
|
||||||
Integer updateGeomPnu(List<FeaturePnuDto> list);
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.postgres.repository;
|
|
||||||
|
|
||||||
import static com.kamco.cd.kamcoback.Innopam.postgres.entity.QDetectMastEntity.detectMastEntity;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.postgres.entity.DetectMastEntity;
|
|
||||||
import com.querydsl.core.BooleanBuilder;
|
|
||||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class DetectMastRepositoryImpl implements DetectMastRepositoryCustom {
|
|
||||||
|
|
||||||
private final EntityManager em;
|
|
||||||
private final JPAQueryFactory queryFactory;
|
|
||||||
private final ObjectMapper objectMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DetectMastEntity> findDetectMastList(DetectMastSearch detectMast) {
|
|
||||||
|
|
||||||
BooleanBuilder whereBuilder = new BooleanBuilder();
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(detectMast.getCprsAdYr())) {
|
|
||||||
whereBuilder.and(detectMastEntity.cprsAdYr.eq(detectMast.getCprsAdYr()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(detectMast.getCprsBfYr())) {
|
|
||||||
whereBuilder.and(detectMastEntity.cprsBfYr.eq(detectMast.getCprsBfYr()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (detectMast.getDtctSno() != null) {
|
|
||||||
whereBuilder.and(detectMastEntity.dtctSno.eq(detectMast.getDtctSno()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return queryFactory.select(detectMastEntity).from(detectMastEntity).where(whereBuilder).fetch();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DetectMastEntity findPnuData(DetectMastSearch detectMast) {
|
|
||||||
|
|
||||||
BooleanBuilder whereBuilder = new BooleanBuilder();
|
|
||||||
|
|
||||||
whereBuilder.and(detectMastEntity.cprsAdYr.eq(detectMast.getCprsAdYr()));
|
|
||||||
whereBuilder.and(detectMastEntity.cprsBfYr.eq(detectMast.getCprsBfYr()));
|
|
||||||
whereBuilder.and(detectMastEntity.dtctSno.eq(detectMast.getDtctSno()));
|
|
||||||
|
|
||||||
if (detectMast.getFeatureId() != null) {
|
|
||||||
whereBuilder.and(detectMastEntity.featureId.eq(detectMast.getFeatureId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return queryFactory
|
|
||||||
.select(detectMastEntity)
|
|
||||||
.from(detectMastEntity)
|
|
||||||
.where(whereBuilder)
|
|
||||||
.fetchOne();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer updateGeomPnu(List<FeaturePnuDto> list) {
|
|
||||||
if (list == null || list.isEmpty()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
String sql =
|
|
||||||
"""
|
|
||||||
UPDATE tb_map_sheet_anal_data_inference_geom g
|
|
||||||
SET pnu = j.pnu
|
|
||||||
FROM (
|
|
||||||
SELECT
|
|
||||||
(elem->>'featureId')::uuid AS feature_uuid,
|
|
||||||
(elem->>'pnu')::bigint AS pnu
|
|
||||||
FROM jsonb_array_elements(CAST(:json AS jsonb)) AS elem
|
|
||||||
) j
|
|
||||||
WHERE g.uuid = j.feature_uuid;
|
|
||||||
""";
|
|
||||||
|
|
||||||
String json = "";
|
|
||||||
try {
|
|
||||||
json = objectMapper.writeValueAsString(list);
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
throw new RuntimeException("PNU 업데이트 실패", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return em.createNativeQuery(sql).setParameter("json", json).executeUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.service;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonFactory;
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import com.fasterxml.jackson.core.JsonToken;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.Basic;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastReq;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.postgres.core.DetectMastCoreService;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class DetectMastService {
|
|
||||||
|
|
||||||
@Value("${spring.profiles.active:local}")
|
|
||||||
private String profile;
|
|
||||||
|
|
||||||
private final DetectMastCoreService detectMastCoreService;
|
|
||||||
private final JsonFactory jsonFactory = new JsonFactory();
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void saveDetectMast(DetectMastReq detectMast) {
|
|
||||||
detectMastCoreService.saveDetectMast(detectMast);
|
|
||||||
//
|
|
||||||
// String dirPath =
|
|
||||||
// "local".equals(profile)
|
|
||||||
// ? "/Users/bokmin/detect/result/2023_2024/4"
|
|
||||||
// : detectMast.getPathNm();
|
|
||||||
//
|
|
||||||
// List<FeaturePnuDto> list = this.extractFeaturePnusRandom(dirPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Basic> selectDetectMast(DetectMastSearch detectMast) {
|
|
||||||
return detectMastCoreService.selectDetectMast(detectMast);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Basic selectDetectMast(Long id) {
|
|
||||||
return detectMastCoreService.selectDetectMast(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** GeoJSON → polygon_id + 랜덤 PNU */
|
|
||||||
public List<FeaturePnuDto> findPnuData(DetectMastSearch detectMast) {
|
|
||||||
|
|
||||||
String dirPath =
|
|
||||||
"local".equals(profile)
|
|
||||||
? "/Users/bokmin/detect/result/"
|
|
||||||
+ detectMast.getCprsBfYr()
|
|
||||||
+ "_"
|
|
||||||
+ detectMast.getCprsAdYr()
|
|
||||||
+ "/"
|
|
||||||
+ detectMast.getDtctSno()
|
|
||||||
: detectMastCoreService.findPnuData(detectMast);
|
|
||||||
|
|
||||||
return extractFeaturePnusRandom(dirPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FeaturePnuDto selectPnuDetail(UUID uuid) {
|
|
||||||
FeaturePnuDto dto = new FeaturePnuDto();
|
|
||||||
dto.setPnu(randomPnu());
|
|
||||||
dto.setFeatureId(uuid.toString());
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public Integer updatePnuData(DetectMastSearch detectMast) {
|
|
||||||
|
|
||||||
String dirPath =
|
|
||||||
"local".equals(profile)
|
|
||||||
? "/Users/bokmin/detect/result/"
|
|
||||||
+ detectMast.getCprsBfYr()
|
|
||||||
+ "_"
|
|
||||||
+ detectMast.getCprsAdYr()
|
|
||||||
+ "/"
|
|
||||||
+ detectMast.getDtctSno()
|
|
||||||
: detectMastCoreService.findPnuData(detectMast);
|
|
||||||
|
|
||||||
List<FeaturePnuDto> list = extractFeaturePnusRandom(dirPath);
|
|
||||||
return detectMastCoreService.updatePnu(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 하위 폴더까지 .geojson 파일들에서 polygon_id만 뽑음 병렬처리(parallel) 제거: IO + parallel은 거의 항상 느려짐 */
|
|
||||||
private List<FeaturePnuDto> extractFeaturePnusRandom(String dirPath) {
|
|
||||||
|
|
||||||
Path basePath = Paths.get(dirPath);
|
|
||||||
if (!Files.isDirectory(basePath)) {
|
|
||||||
System.err.println("유효하지 않은 디렉터리: " + dirPath);
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<FeaturePnuDto> out = new ArrayList<>(4096);
|
|
||||||
|
|
||||||
try (Stream<Path> stream = Files.walk(basePath)) {
|
|
||||||
stream
|
|
||||||
.filter(Files::isRegularFile)
|
|
||||||
.filter(p -> p.toString().toLowerCase().endsWith(".geojson"))
|
|
||||||
.forEach(
|
|
||||||
p -> {
|
|
||||||
try (InputStream in = Files.newInputStream(p);
|
|
||||||
JsonParser parser = jsonFactory.createParser(in)) {
|
|
||||||
|
|
||||||
while (parser.nextToken() != null) {
|
|
||||||
if (parser.currentToken() == JsonToken.FIELD_NAME
|
|
||||||
&& "polygon_id".equals(parser.getCurrentName())) {
|
|
||||||
|
|
||||||
JsonToken next = parser.nextToken(); // 값으로 이동
|
|
||||||
if (next == JsonToken.VALUE_STRING) {
|
|
||||||
String polygonId = parser.getValueAsString();
|
|
||||||
out.add(new FeaturePnuDto(polygonId, randomPnu()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
// 파일 단위 실패는 최소 로그
|
|
||||||
System.err.println("GeoJSON 파싱 실패: " + p.getFileName() + " / " + e.getMessage());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.err.println("디렉터리 탐색 실패: " + e.getMessage());
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 랜덤 PNU 생성 (임시) - 법정동코드(5) + 산구분(1) + 본번(4) + 부번(4) = 14자리 */
|
|
||||||
private String randomPnu() {
|
|
||||||
ThreadLocalRandom r = ThreadLocalRandom.current();
|
|
||||||
|
|
||||||
String dongCode = String.format("%05d", r.nextInt(10000, 99999));
|
|
||||||
String san = r.nextBoolean() ? "1" : "2";
|
|
||||||
String bon = String.format("%04d", r.nextInt(1, 10000));
|
|
||||||
String bu = String.format("%04d", r.nextInt(0, 10000));
|
|
||||||
|
|
||||||
return dongCode + san + bon + bu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.service;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonFactory;
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import com.fasterxml.jackson.core.JsonToken;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.ChngDetectMastDto;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.ChngDetectMastDto.ChngDetectMastSearchDto;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.ChngDetectMastDto.ResReturn;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.Basic;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastReq;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto;
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.postgres.core.DetectMastCoreService;
|
|
||||||
import com.kamco.cd.kamcoback.common.utils.NetUtils;
|
|
||||||
import com.kamco.cd.kamcoback.common.utils.UserUtil;
|
|
||||||
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
|
|
||||||
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient;
|
|
||||||
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult;
|
|
||||||
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.DmlReturn;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class InnopamApiService {
|
|
||||||
|
|
||||||
@Value("${spring.profiles.active:local}")
|
|
||||||
private String profile;
|
|
||||||
|
|
||||||
@Value("${innopam.url}")
|
|
||||||
private String innopamUrl;
|
|
||||||
|
|
||||||
@Value("${innopam.mast}")
|
|
||||||
private String innopamMastUrl;
|
|
||||||
|
|
||||||
|
|
||||||
private final DetectMastCoreService detectMastCoreService;
|
|
||||||
|
|
||||||
private final ExternalHttpClient externalHttpClient;
|
|
||||||
private final UserUtil userUtil = new UserUtil();
|
|
||||||
private final NetUtils netUtils = new NetUtils();
|
|
||||||
|
|
||||||
private final JsonFactory jsonFactory = new JsonFactory();
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public ChngDetectMastDto.Basic regist(ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) {
|
|
||||||
|
|
||||||
ChngDetectMastDto.Basic basic = new ChngDetectMastDto.Basic();
|
|
||||||
|
|
||||||
String url = innopamMastUrl + "/regist";
|
|
||||||
//url = "http://localhost:8080/api/kcd/cdi/detect/mast/regist";
|
|
||||||
|
|
||||||
String myip = netUtils.getLocalIP();
|
|
||||||
chnDetectMastReq.setReqIp(myip);
|
|
||||||
|
|
||||||
System.out.println("url == "+ url);
|
|
||||||
System.out.println("url == "+ myip);
|
|
||||||
|
|
||||||
ExternalCallResult<String> result =
|
|
||||||
externalHttpClient.call(url, HttpMethod.POST, chnDetectMastReq, netUtils.jsonHeaders(), String.class);
|
|
||||||
|
|
||||||
System.out.println("result == " + result);
|
|
||||||
|
|
||||||
return basic;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public ResReturn remove(ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) {
|
|
||||||
ChngDetectMastDto.Basic basic = new ChngDetectMastDto.Basic();
|
|
||||||
|
|
||||||
String url = innopamMastUrl + "/remove";
|
|
||||||
//url = "http://localhost:8080/api/kcd/cdi/detect/mast/remove";
|
|
||||||
|
|
||||||
String myip = netUtils.getLocalIP();
|
|
||||||
chnDetectMastReq.setReqIp(myip);
|
|
||||||
|
|
||||||
System.out.println("url == "+ url);
|
|
||||||
System.out.println("url == "+ myip);
|
|
||||||
|
|
||||||
ExternalCallResult<String> result =
|
|
||||||
externalHttpClient.call(url, HttpMethod.POST, chnDetectMastReq, netUtils.jsonHeaders(), String.class);
|
|
||||||
|
|
||||||
System.out.println("result == " + result);
|
|
||||||
|
|
||||||
return new ResReturn("success", "탐지결과 삭제 되었습니다.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public List<ChngDetectMastDto.Basic> list(ChngDetectMastDto.ChngDetectMastSearchDto searchDto) {
|
|
||||||
List<ChngDetectMastDto.Basic> masterList = new ArrayList<>();
|
|
||||||
|
|
||||||
String queryString = netUtils.dtoToQueryString(searchDto, null);
|
|
||||||
String url = innopamMastUrl+queryString;
|
|
||||||
|
|
||||||
ExternalCallResult<String> result =
|
|
||||||
externalHttpClient.call(url, HttpMethod.GET, null, netUtils.jsonHeaders(), String.class);
|
|
||||||
|
|
||||||
System.out.println("list result == " + result);
|
|
||||||
|
|
||||||
return masterList;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.utils;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import org.locationtech.jts.geom.Coordinate;
|
|
||||||
import org.locationtech.jts.geom.Geometry;
|
|
||||||
import org.locationtech.jts.geom.GeometryFactory;
|
|
||||||
import org.locationtech.jts.geom.LinearRing;
|
|
||||||
import org.locationtech.jts.geom.MultiPolygon;
|
|
||||||
import org.locationtech.jts.geom.Polygon;
|
|
||||||
|
|
||||||
public class GeoJsonGeometryConverter {
|
|
||||||
|
|
||||||
private static final GeometryFactory GF = new GeometryFactory();
|
|
||||||
|
|
||||||
public static Geometry toGeometry(JsonNode geomNode) {
|
|
||||||
String type = geomNode.path("type").asText();
|
|
||||||
|
|
||||||
if ("Polygon".equals(type)) {
|
|
||||||
return toPolygon(geomNode.path("coordinates"));
|
|
||||||
}
|
|
||||||
if ("MultiPolygon".equals(type)) {
|
|
||||||
return toMultiPolygon(geomNode.path("coordinates"));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Polygon toPolygon(JsonNode coords) {
|
|
||||||
LinearRing shell = GF.createLinearRing(toCoords(coords.get(0)));
|
|
||||||
return GF.createPolygon(shell);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MultiPolygon toMultiPolygon(JsonNode coords) {
|
|
||||||
Polygon[] polys = new Polygon[coords.size()];
|
|
||||||
for (int i = 0; i < coords.size(); i++) {
|
|
||||||
polys[i] = toPolygon(coords.get(i));
|
|
||||||
}
|
|
||||||
return GF.createMultiPolygon(polys);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Coordinate[] toCoords(JsonNode ring) {
|
|
||||||
Coordinate[] c = new Coordinate[ring.size() + 1];
|
|
||||||
for (int i = 0; i < ring.size(); i++) {
|
|
||||||
c[i] = new Coordinate(ring.get(i).get(0).asDouble(), ring.get(i).get(1).asDouble());
|
|
||||||
}
|
|
||||||
c[c.length - 1] = c[0];
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.utils;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class GeoJsonLoader {
|
|
||||||
|
|
||||||
private final ObjectMapper om = new ObjectMapper();
|
|
||||||
|
|
||||||
public GeoJsonFile load(File geoJsonFile) throws Exception {
|
|
||||||
|
|
||||||
JsonNode root = om.readTree(geoJsonFile);
|
|
||||||
|
|
||||||
long mapId = root.path("properties").path("map_id").asLong(-1);
|
|
||||||
if (mapId <= 0) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"GeoJSON top-level properties.map_id 없음: " + geoJsonFile.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<JsonNode> features = new ArrayList<>();
|
|
||||||
root.path("features").forEach(features::add);
|
|
||||||
|
|
||||||
return new GeoJsonFile(mapId, features);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ✅ feature에서 polygon_id 추출 */
|
|
||||||
public static String polygonId(JsonNode feature) {
|
|
||||||
return feature.path("properties").path("polygon_id").asText(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class GeoJsonFile {
|
|
||||||
|
|
||||||
public final long mapId;
|
|
||||||
public final List<JsonNode> features;
|
|
||||||
|
|
||||||
public GeoJsonFile(long mapId, List<JsonNode> features) {
|
|
||||||
this.mapId = mapId;
|
|
||||||
this.features = features;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.utils;
|
|
||||||
|
|
||||||
public class MapIdUtils {
|
|
||||||
|
|
||||||
private MapIdUtils() {
|
|
||||||
// util class
|
|
||||||
}
|
|
||||||
|
|
||||||
/** map_id → 시도코드 예: 34602060 → "34" */
|
|
||||||
public static String sidoCodeFromMapId(long mapId) {
|
|
||||||
String s = String.valueOf(mapId);
|
|
||||||
if (s.length() < 2) {
|
|
||||||
throw new IllegalArgumentException("잘못된 map_id: " + mapId);
|
|
||||||
}
|
|
||||||
return s.substring(0, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.utils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import org.geotools.api.data.DataStore;
|
|
||||||
import org.geotools.api.data.DataStoreFinder;
|
|
||||||
import org.geotools.api.data.SimpleFeatureSource;
|
|
||||||
import org.geotools.api.feature.simple.SimpleFeature;
|
|
||||||
import org.geotools.data.simple.SimpleFeatureCollection;
|
|
||||||
import org.geotools.data.simple.SimpleFeatureIterator;
|
|
||||||
import org.locationtech.jts.geom.Geometry;
|
|
||||||
import org.locationtech.jts.index.strtree.STRtree;
|
|
||||||
|
|
||||||
public class ShpIndexManager {
|
|
||||||
|
|
||||||
private static final String SHP_ROOT = "/shp";
|
|
||||||
private static final String SHP_YYYYMM = "202512";
|
|
||||||
private static final String PNU_FIELD = "PNU";
|
|
||||||
|
|
||||||
private final Map<String, STRtree> cache = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
public STRtree getIndex(String sidoCode) {
|
|
||||||
return cache.computeIfAbsent(sidoCode, this::loadIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private STRtree loadIndex(String sidoCode) {
|
|
||||||
try {
|
|
||||||
String path = SHP_ROOT + "/LSMD_CONT_LDREG_" + sidoCode + "_" + SHP_YYYYMM + ".shp";
|
|
||||||
|
|
||||||
File shp = new File(path);
|
|
||||||
if (!shp.exists()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
STRtree index = new STRtree(10);
|
|
||||||
|
|
||||||
DataStore store = DataStoreFinder.getDataStore(Map.of("url", shp.toURI().toURL()));
|
|
||||||
|
|
||||||
String typeName = store.getTypeNames()[0];
|
|
||||||
SimpleFeatureSource source = store.getFeatureSource(typeName);
|
|
||||||
SimpleFeatureCollection col = source.getFeatures();
|
|
||||||
|
|
||||||
try (SimpleFeatureIterator it = col.features()) {
|
|
||||||
while (it.hasNext()) {
|
|
||||||
SimpleFeature f = it.next();
|
|
||||||
Geometry geom = (Geometry) f.getDefaultGeometry();
|
|
||||||
String pnu = Objects.toString(f.getAttribute(PNU_FIELD), null);
|
|
||||||
if (geom != null && pnu != null) {
|
|
||||||
index.insert(geom.getEnvelopeInternal(), new ShpRow(geom, pnu));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
index.build();
|
|
||||||
store.dispose();
|
|
||||||
return index;
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** SHP 한 row */
|
|
||||||
public static class ShpRow {
|
|
||||||
|
|
||||||
public final Geometry geom;
|
|
||||||
public final String pnu;
|
|
||||||
|
|
||||||
public ShpRow(Geometry geom, String pnu) {
|
|
||||||
this.geom = geom;
|
|
||||||
this.pnu = pnu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.utils;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import org.locationtech.jts.geom.Envelope;
|
|
||||||
import org.locationtech.jts.geom.Geometry;
|
|
||||||
import org.locationtech.jts.geom.prep.PreparedGeometry;
|
|
||||||
import org.locationtech.jts.geom.prep.PreparedGeometryFactory;
|
|
||||||
import org.locationtech.jts.index.strtree.STRtree;
|
|
||||||
|
|
||||||
public class ShpPnuMatcher {
|
|
||||||
|
|
||||||
public static String pickByIntersectionMax(STRtree index, Geometry target) {
|
|
||||||
|
|
||||||
Envelope env = target.getEnvelopeInternal();
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<ShpIndexManager.ShpRow> rows = index.query(env);
|
|
||||||
|
|
||||||
double best = 0;
|
|
||||||
String bestPnu = null;
|
|
||||||
|
|
||||||
for (ShpIndexManager.ShpRow row : rows) {
|
|
||||||
|
|
||||||
PreparedGeometry prep = PreparedGeometryFactory.prepare(row.geom);
|
|
||||||
|
|
||||||
if (prep.contains(target) || prep.covers(target)) {
|
|
||||||
return row.pnu;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!prep.intersects(target)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double area = row.geom.intersection(target).getArea();
|
|
||||||
if (area > best) {
|
|
||||||
best = area;
|
|
||||||
bestPnu = row.pnu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bestPnu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,10 @@ package com.kamco.cd.kamcoback.auth;
|
|||||||
import com.kamco.cd.kamcoback.common.enums.StatusType;
|
import com.kamco.cd.kamcoback.common.enums.StatusType;
|
||||||
import com.kamco.cd.kamcoback.common.enums.error.AuthErrorCode;
|
import com.kamco.cd.kamcoback.common.enums.error.AuthErrorCode;
|
||||||
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
||||||
|
import com.kamco.cd.kamcoback.common.utils.HeaderUtil;
|
||||||
import com.kamco.cd.kamcoback.postgres.entity.MemberEntity;
|
import com.kamco.cd.kamcoback.postgres.entity.MemberEntity;
|
||||||
import com.kamco.cd.kamcoback.postgres.repository.members.MembersRepository;
|
import com.kamco.cd.kamcoback.postgres.repository.members.MembersRepository;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.mindrot.jbcrypt.BCrypt;
|
import org.mindrot.jbcrypt.BCrypt;
|
||||||
import org.springframework.security.authentication.AuthenticationProvider;
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
@@ -12,12 +14,16 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
|
|||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class CustomAuthenticationProvider implements AuthenticationProvider {
|
public class CustomAuthenticationProvider implements AuthenticationProvider {
|
||||||
|
|
||||||
private final MembersRepository membersRepository;
|
private final MembersRepository membersRepository;
|
||||||
|
ServletRequestAttributes attr =
|
||||||
|
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
@@ -52,7 +58,15 @@ public class CustomAuthenticationProvider implements AuthenticationProvider {
|
|||||||
// 인증 성공 → UserDetails 생성
|
// 인증 성공 → UserDetails 생성
|
||||||
CustomUserDetails userDetails = new CustomUserDetails(member);
|
CustomUserDetails userDetails = new CustomUserDetails(member);
|
||||||
|
|
||||||
return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
// front에서 전달한 사용자 ip 등록
|
||||||
|
HttpServletRequest req = (attr != null) ? attr.getRequest() : null;
|
||||||
|
String ip = (req != null) ? HeaderUtil.get(req, "X-Forwarded-For") : null;
|
||||||
|
|
||||||
|
UsernamePasswordAuthenticationToken token =
|
||||||
|
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||||
|
|
||||||
|
token.setDetails(ip);
|
||||||
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import lombok.Getter;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum StatusType implements EnumType {
|
public enum StatusType implements EnumType {
|
||||||
ACTIVE("사용"),
|
ACTIVE("사용"),
|
||||||
INACTIVE("미사용"),
|
INACTIVE("사용중지"),
|
||||||
PENDING("계정등록");
|
PENDING("계정등록");
|
||||||
|
|
||||||
private final String desc;
|
private final String desc;
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.kamco.cd.kamcoback.common.utils;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
public final class HeaderUtil {
|
||||||
|
|
||||||
|
private HeaderUtil() {}
|
||||||
|
|
||||||
|
/** 특정 Header 값 조회 */
|
||||||
|
public static String get(HttpServletRequest request, String headerName) {
|
||||||
|
if (request == null || headerName == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String value = request.getHeader(headerName);
|
||||||
|
return (value != null && !value.isBlank()) ? value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 필수 Header 조회 (없으면 null) */
|
||||||
|
public static String getRequired(HttpServletRequest request, String headerName) {
|
||||||
|
return get(request, headerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,15 +7,13 @@ import java.net.UnknownHostException;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import org.mindrot.jbcrypt.BCrypt;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
public class NetUtils {
|
public class NetUtils {
|
||||||
|
|
||||||
public String getLocalIP(){
|
public String getLocalIP() {
|
||||||
|
|
||||||
String ip;
|
String ip;
|
||||||
{
|
{
|
||||||
@@ -30,23 +28,26 @@ public class NetUtils {
|
|||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String dtoToQueryString(Object dto, String queryString) {
|
public String dtoToQueryString(Object dto, String queryString) {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
Map<String, Object> map = objectMapper.convertValue(dto, Map.class);
|
Map<String, Object> map = objectMapper.convertValue(dto, Map.class);
|
||||||
|
|
||||||
String qStr = map.entrySet().stream()
|
String qStr =
|
||||||
.filter(entry -> entry.getValue() != null) // null 제외
|
map.entrySet().stream()
|
||||||
.map(entry -> String.format("%s=%s",
|
.filter(entry -> entry.getValue() != null) // null 제외
|
||||||
entry.getKey(),
|
.map(
|
||||||
URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8)))
|
entry ->
|
||||||
.collect(Collectors.joining("&"));
|
String.format(
|
||||||
|
"%s=%s",
|
||||||
|
entry.getKey(),
|
||||||
|
URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8)))
|
||||||
|
.collect(Collectors.joining("&"));
|
||||||
|
|
||||||
if( queryString == null || queryString.isEmpty() ) {
|
if (queryString == null || queryString.isEmpty()) {
|
||||||
queryString = "?"+qStr;
|
queryString = "?" + qStr;
|
||||||
}else{
|
} else {
|
||||||
queryString = queryString +"&" + qStr;
|
queryString = queryString + "&" + qStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Map을 쿼리 스트링 문자열로 변환
|
// 2. Map을 쿼리 스트링 문자열로 변환
|
||||||
@@ -60,5 +61,4 @@ public class NetUtils {
|
|||||||
|
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,4 +44,11 @@ public class UserUtil {
|
|||||||
MembersDto.Member user = getCurrentUser();
|
MembersDto.Member user = getCurrentUser();
|
||||||
return user != null ? user.getRole() : null;
|
return user != null ? user.getRole() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getIp() {
|
||||||
|
return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
|
||||||
|
.map(auth -> auth.getDetails())
|
||||||
|
.map(Object::toString)
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.kamco.cd.kamcoback.config;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.kamco.cd.kamcoback.auth.CustomUserDetails;
|
import com.kamco.cd.kamcoback.auth.CustomUserDetails;
|
||||||
|
import com.kamco.cd.kamcoback.common.utils.HeaderUtil;
|
||||||
import com.kamco.cd.kamcoback.config.api.ApiLogFunction;
|
import com.kamco.cd.kamcoback.config.api.ApiLogFunction;
|
||||||
import com.kamco.cd.kamcoback.menu.dto.MenuDto;
|
import com.kamco.cd.kamcoback.menu.dto.MenuDto;
|
||||||
import com.kamco.cd.kamcoback.menu.service.MenuService;
|
import com.kamco.cd.kamcoback.menu.service.MenuService;
|
||||||
@@ -13,6 +14,7 @@ import java.util.Comparator;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
@@ -74,7 +76,8 @@ public class FileDownloadInteceptor implements HandlerInterceptor {
|
|||||||
request.getRequestURI(),
|
request.getRequestURI(),
|
||||||
Objects.requireNonNull(basic).getMenuUid(),
|
Objects.requireNonNull(basic).getMenuUid(),
|
||||||
ip,
|
ip,
|
||||||
response.getStatus());
|
response.getStatus(),
|
||||||
|
UUID.fromString(HeaderUtil.get(request, "kamco-download-uuid")));
|
||||||
|
|
||||||
auditLogRepository.save(log);
|
auditLogRepository.save(log);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -378,7 +378,7 @@ public class GlobalExceptionHandler {
|
|||||||
HttpStatus.valueOf(codeName),
|
HttpStatus.valueOf(codeName),
|
||||||
errorLog.getId());
|
errorLog.getId());
|
||||||
|
|
||||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED) // 🔥 여기서 401 지정
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED) // 여기서 401 지정
|
||||||
.body(body);
|
.body(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ import java.util.Comparator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.util.ContentCachingRequestWrapper;
|
import org.springframework.web.util.ContentCachingRequestWrapper;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ApiLogFunction {
|
public class ApiLogFunction {
|
||||||
|
|
||||||
// 클라이언트 IP 추출
|
// 클라이언트 IP 추출
|
||||||
@@ -35,6 +37,14 @@ public class ApiLogFunction {
|
|||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getXFowardedForIp(HttpServletRequest request) {
|
||||||
|
String ip = request.getHeader("X-Forwarded-For");
|
||||||
|
if (ip != null) {
|
||||||
|
ip = ip.split(",")[0].trim();
|
||||||
|
}
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
// 사용자 ID 추출 예시 (Spring Security 기준)
|
// 사용자 ID 추출 예시 (Spring Security 기준)
|
||||||
public static String getUserId(HttpServletRequest request) {
|
public static String getUserId(HttpServletRequest request) {
|
||||||
try {
|
try {
|
||||||
@@ -53,15 +63,15 @@ public class ApiLogFunction {
|
|||||||
return EventType.DOWNLOAD;
|
return EventType.DOWNLOAD;
|
||||||
}
|
}
|
||||||
if (uri.contains("/print")) {
|
if (uri.contains("/print")) {
|
||||||
return EventType.PRINT;
|
return EventType.OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 일반 CRUD
|
// 일반 CRUD
|
||||||
return switch (method) {
|
return switch (method) {
|
||||||
case "POST" -> EventType.CREATE;
|
case "POST" -> EventType.ADDED;
|
||||||
case "GET" -> EventType.READ;
|
case "GET" -> EventType.LIST;
|
||||||
case "DELETE" -> EventType.DELETE;
|
case "DELETE" -> EventType.REMOVE;
|
||||||
case "PUT", "PATCH" -> EventType.UPDATE;
|
case "PUT", "PATCH" -> EventType.MODIFIED;
|
||||||
default -> EventType.OTHER;
|
default -> EventType.OTHER;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.kamco.cd.kamcoback.config.api;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.kamco.cd.kamcoback.auth.CustomUserDetails;
|
import com.kamco.cd.kamcoback.auth.CustomUserDetails;
|
||||||
|
import com.kamco.cd.kamcoback.common.utils.HeaderUtil;
|
||||||
|
import com.kamco.cd.kamcoback.log.dto.EventType;
|
||||||
import com.kamco.cd.kamcoback.menu.dto.MenuDto;
|
import com.kamco.cd.kamcoback.menu.dto.MenuDto;
|
||||||
import com.kamco.cd.kamcoback.menu.service.MenuService;
|
import com.kamco.cd.kamcoback.menu.service.MenuService;
|
||||||
import com.kamco.cd.kamcoback.postgres.entity.AuditLogEntity;
|
import com.kamco.cd.kamcoback.postgres.entity.AuditLogEntity;
|
||||||
@@ -66,12 +68,23 @@ public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
|
|||||||
if (body instanceof ApiResponseDto<?> apiResponse) {
|
if (body instanceof ApiResponseDto<?> apiResponse) {
|
||||||
response.setStatusCode(apiResponse.getHttpStatus());
|
response.setStatusCode(apiResponse.getHttpStatus());
|
||||||
|
|
||||||
String ip = ApiLogFunction.getClientIp(servletRequest);
|
String actionType = HeaderUtil.get(servletRequest, "kamco-action-type");
|
||||||
Long userid = null;
|
if (actionType == null) { // actionType 이 없으면 로그 저장하지 않기
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
if (servletRequest.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth
|
String ip = ApiLogFunction.getXFowardedForIp(servletRequest);
|
||||||
&& auth.getPrincipal() instanceof CustomUserDetails customUserDetails) {
|
Long userid = null;
|
||||||
userid = customUserDetails.getMember().getId();
|
String loginAttemptId = null;
|
||||||
|
|
||||||
|
// 로그인 시도할 때
|
||||||
|
if (servletRequest.getRequestURI().contains("/api/auth/signin")) {
|
||||||
|
loginAttemptId = HeaderUtil.get(servletRequest, "kamco-login-attempt-id");
|
||||||
|
} else {
|
||||||
|
if (servletRequest.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth
|
||||||
|
&& auth.getPrincipal() instanceof CustomUserDetails customUserDetails) {
|
||||||
|
userid = customUserDetails.getMember().getId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String requestBody;
|
String requestBody;
|
||||||
@@ -107,13 +120,15 @@ public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
|
|||||||
AuditLogEntity log =
|
AuditLogEntity log =
|
||||||
new AuditLogEntity(
|
new AuditLogEntity(
|
||||||
userid,
|
userid,
|
||||||
ApiLogFunction.getEventType(servletRequest),
|
EventType.fromName(actionType),
|
||||||
ApiLogFunction.isSuccessFail(apiResponse),
|
ApiLogFunction.isSuccessFail(apiResponse),
|
||||||
ApiLogFunction.getUriMenuInfo(result, servletRequest.getRequestURI()),
|
ApiLogFunction.getUriMenuInfo(result, servletRequest.getRequestURI()),
|
||||||
ip,
|
ip,
|
||||||
servletRequest.getRequestURI(),
|
servletRequest.getRequestURI(),
|
||||||
ApiLogFunction.cutRequestBody(requestBody),
|
ApiLogFunction.cutRequestBody(requestBody),
|
||||||
apiResponse.getErrorLogUid());
|
apiResponse.getErrorLogUid(),
|
||||||
|
null,
|
||||||
|
loginAttemptId);
|
||||||
auditLogRepository.save(log);
|
auditLogRepository.save(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam;
|
package com.kamco.cd.kamcoback.gukyuin;
|
||||||
|
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.ChngDetectMastDto;
|
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.ChngDetectMastDto.ChnDetectMastReqDto;
|
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto;
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.ChngDetectMastDto.ChngDetectMastSearchDto;
|
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ChnDetectMastReqDto;
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.ChngDetectMastDto.ResReturn;
|
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ChngDetectMastSearchDto;
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.Basic;
|
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResReturn;
|
||||||
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastReq;
|
import com.kamco.cd.kamcoback.gukyuin.dto.DetectMastDto.Basic;
|
||||||
import com.kamco.cd.kamcoback.Innopam.service.InnopamApiService;
|
import com.kamco.cd.kamcoback.gukyuin.dto.DetectMastDto.DetectMastReq;
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkableRes;
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.service.GukYuinApiService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.media.Content;
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
@@ -15,21 +18,23 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
|||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
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.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@Tag(name = "이노펨 연동 API", description = "이노펨 연동 API")
|
@Tag(name = "국유in 연동 API", description = "국유in 연동 API")
|
||||||
@RestController
|
@RestController
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RequestMapping("/api/innopam/")
|
@RequestMapping("/api/gukyuin/")
|
||||||
public class InnopamApiController {
|
public class GukYuinApiController {
|
||||||
|
|
||||||
private final InnopamApiService innopamApiService;
|
private final GukYuinApiService gukYuinApiService;
|
||||||
|
|
||||||
/** 탐지결과 등록 */
|
/** 탐지결과 등록 */
|
||||||
@Operation(summary = "탐지결과 등록", description = "탐지결과 등록")
|
@Operation(summary = "탐지결과 등록", description = "탐지결과 등록")
|
||||||
@@ -48,8 +53,7 @@ public class InnopamApiController {
|
|||||||
@PostMapping("/mast/regist")
|
@PostMapping("/mast/regist")
|
||||||
public ChngDetectMastDto.Basic regist(
|
public ChngDetectMastDto.Basic regist(
|
||||||
@RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) {
|
@RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) {
|
||||||
// innopamApiService.saveDetectMast(chnDetectMastReq);
|
return gukYuinApiService.regist(chnDetectMastReq);
|
||||||
return innopamApiService.regist(chnDetectMastReq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "탐지결과 삭제", description = "탐지결과 삭제")
|
@Operation(summary = "탐지결과 삭제", description = "탐지결과 삭제")
|
||||||
@@ -68,7 +72,7 @@ public class InnopamApiController {
|
|||||||
@PostMapping("/mast/remove")
|
@PostMapping("/mast/remove")
|
||||||
public ResReturn remove(
|
public ResReturn remove(
|
||||||
@RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) {
|
@RequestBody @Valid ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) {
|
||||||
return innopamApiService.remove(chnDetectMastReq);
|
return gukYuinApiService.remove(chnDetectMastReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "탐지결과 등록목록 조회", description = "탐지결과 등록목록 조회")
|
@Operation(summary = "탐지결과 등록목록 조회", description = "탐지결과 등록목록 조회")
|
||||||
@@ -95,6 +99,30 @@ public class InnopamApiController {
|
|||||||
searchDto.setCprsYr(cprsYr);
|
searchDto.setCprsYr(cprsYr);
|
||||||
searchDto.setCrtrYr(crtrYr);
|
searchDto.setCrtrYr(crtrYr);
|
||||||
searchDto.setChnDtctSno(chnDtctSno);
|
searchDto.setChnDtctSno(chnDtctSno);
|
||||||
return innopamApiService.list(searchDto);
|
return gukYuinApiService.list(searchDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "국유in연동 가능여부 확인", description = "국유in연동 가능여부 확인")
|
||||||
|
@GetMapping("/is-link/{uuid}")
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "목록 성공",
|
||||||
|
content =
|
||||||
|
@Content(
|
||||||
|
mediaType = "application/json",
|
||||||
|
schema =
|
||||||
|
@Schema(
|
||||||
|
implementation = GukYuinLinkableRes.class,
|
||||||
|
description = "TRUE:연동가능, FALSE:연동 불가능"))),
|
||||||
|
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
|
})
|
||||||
|
public ApiResponseDto<GukYuinLinkableRes> getIsLinkGukYuin(
|
||||||
|
@Parameter(description = "uuid", example = "5799eb21-4780-48b0-a82e-e58dcbb8806b")
|
||||||
|
@PathVariable
|
||||||
|
UUID uuid) {
|
||||||
|
return ApiResponseDto.ok(gukYuinApiService.getIsLinkGukYuin(uuid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
package com.kamco.cd.kamcoback.gukyuin.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class ChngDetectMastDto {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class Basic {
|
||||||
|
|
||||||
|
private String chnDtctMstId; // 탐지마스터아이디
|
||||||
|
private String cprsYr; // 비교년도 2023
|
||||||
|
private String crtrYr; // 기준년도 2024
|
||||||
|
private String chnDtctSno; // 차수 (1 | 2 | ...)
|
||||||
|
private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
||||||
|
private String chnDtctCnt; // 탐지객체개수
|
||||||
|
private String pnuMpngCnt; // PNU매핑개수
|
||||||
|
private String lrmYmd; // 지적도일자
|
||||||
|
private String pathNm; // 탐지결과 절대경로명 /kamco_nas/export/{chnDtctId}
|
||||||
|
private List<ChnDetectMastExcnStepDto> excnList; // 등록진행상태히스토리 (최근것부터 DESC)
|
||||||
|
private String excnStepCd; // 실행단계코드
|
||||||
|
private String excnStep; // 실행단계코드에 해당하는 영문명
|
||||||
|
private String excnPgrt; // 실행단계진행율
|
||||||
|
private String excnBngnDt; // 실행단계시작시간
|
||||||
|
private String excnEndDt; // 실행단계종료시간
|
||||||
|
private String rmk; // 비고
|
||||||
|
private String crtDt; // 생성일시
|
||||||
|
private String crtEpno; // 생성사원번호
|
||||||
|
private String crtIp; // 생성사원아이피
|
||||||
|
private String chgDt; // 변경일시
|
||||||
|
private String chgEpno; // 변경사원번호
|
||||||
|
private String chgIp; // 변경사원아이피
|
||||||
|
private String delYn; // 삭제여부
|
||||||
|
//
|
||||||
|
private String reqEpno; // 요청사원번호
|
||||||
|
private String reqIp; // 요청사원어이피
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class ChnDetectMastExcnStepDto {
|
||||||
|
|
||||||
|
private String srno; // 일련번호
|
||||||
|
private String chnDtctMstId; // 탐지마스터아이디
|
||||||
|
private String excnStepCd; // 실행단계코드
|
||||||
|
private String excnStep; // 실행단계코드에 해당하는 영문명
|
||||||
|
private String excnPgrt; // 실행단계진행율
|
||||||
|
private String excnEndDt; // 실행단계종료시간
|
||||||
|
private String errCd; // 오류코드
|
||||||
|
private String errMsg; // 오류메세지
|
||||||
|
private String crtDt; // 실행단계시작시간
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class ChnDetectMastReqDto {
|
||||||
|
|
||||||
|
private String cprsYr; // 비교년도 2023
|
||||||
|
private String crtrYr; // 기준년도 2024
|
||||||
|
private String chnDtctSno; // 차수 (1 | 2 | ...)
|
||||||
|
private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
||||||
|
private String pathNm; // 탐지결과 절대경로명 /kamco_nas/export/{chnDtctId}
|
||||||
|
private String reqEpno; // 사원번호
|
||||||
|
private String reqIp; // 사원아이피
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class ChnDetectContDto {
|
||||||
|
|
||||||
|
private String chnDtctMstId; // 탐지콘텐츠아이디
|
||||||
|
private String chnDtctContId; // 탐지마스타아이디
|
||||||
|
private String cprsYr; // 비교년도 2023
|
||||||
|
private String crtrYr; // 기준년도 2024
|
||||||
|
private String chnDtctSno; // 차수 (1 | 2 | ...)
|
||||||
|
private String mpqdNo; // 도엽번호
|
||||||
|
private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
||||||
|
private String chnDtctObjtId; // 탐지객체아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
||||||
|
private String chnDtctPolygon; // 탐지객체폴리곤
|
||||||
|
private String chnDtctSqms; // 탐지객체면적
|
||||||
|
private String chnCd; // 변화코드
|
||||||
|
private String chnDtctJson; // 변화탐지JSON
|
||||||
|
private String chnDtctProb; // 변화탐지정확도
|
||||||
|
private String bfClsCd; // 이전부류코드
|
||||||
|
private String bfClsProb; // 이전분류정확도
|
||||||
|
private String afClsCd; // 이후분류코드
|
||||||
|
private String afClsProb; // 이후분류정확도
|
||||||
|
private String crtDt; // 생성일시
|
||||||
|
private String crtEpno; // 생성사원번호
|
||||||
|
private String crtIp; // 생성사원아이피
|
||||||
|
private String delYn; // 삭제여부
|
||||||
|
//
|
||||||
|
private String reqEpno; // 요청사원번호
|
||||||
|
private String reqIp; // 요청사원아이피
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class ChnDetectContReqDto {
|
||||||
|
|
||||||
|
private String cprsYr; // 비교년도 2023
|
||||||
|
private String crtrYr; // 기준년도 2024
|
||||||
|
private String chnDtctSno; // 차수 (1 | 2 | ...)
|
||||||
|
private String mpqdNo; // 도엽번호
|
||||||
|
private String chnDtctId; // 탐지아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
||||||
|
private String chnDtctObjtId; // 탐지객체아이디. UUID를 기반으로 '-'를 제거하고 대문자/숫자로 구성
|
||||||
|
private String reqEpno; // 사원번호
|
||||||
|
private String reqIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class ChngDetectMastSearchDto {
|
||||||
|
|
||||||
|
private String chnDtctId;
|
||||||
|
private String cprsYr;
|
||||||
|
private String crtrYr;
|
||||||
|
private String chnDtctSno;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Schema(name = "ResReturn", description = "수행 후 리턴")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class ResReturn {
|
||||||
|
|
||||||
|
private String flag;
|
||||||
|
private String message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.kamco.cd.kamcoback.Innopam.dto;
|
package com.kamco.cd.kamcoback.gukyuin.dto;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.kamco.cd.kamcoback.gukyuin.dto;
|
||||||
|
|
||||||
|
import com.kamco.cd.kamcoback.common.utils.enums.EnumType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class GukYuinDto {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public static class GukYuinLinkableRes {
|
||||||
|
|
||||||
|
private boolean linkable;
|
||||||
|
// private GukYuinLinkFailCode code;
|
||||||
|
private String message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 실패 코드 enum */
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum GukYuinLinkFailCode implements EnumType {
|
||||||
|
OK("연동 가능"),
|
||||||
|
NOT_FOUND("대상 회차가 없습니다."),
|
||||||
|
SCOPE_PART_NOT_ALLOWED("부분 도엽은 연동 불가능 합니다."),
|
||||||
|
HAS_RUNNING_INFERENCE("라벨링 진행 중 회차가 있습니다."),
|
||||||
|
OTHER_GUKYUIN_IN_PROGRESS("국유in 연동 진행 중 회차가 있습니다.");
|
||||||
|
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return name();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText() {
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repository가 반환할 Fact(조회 결과)
|
||||||
|
public record GukYuinLinkFacts(
|
||||||
|
boolean existsLearn,
|
||||||
|
boolean isPartScope,
|
||||||
|
boolean hasRunningInference,
|
||||||
|
boolean hasOtherUnfinishedGukYuin) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.kamco.cd.kamcoback.gukyuin.dto;
|
||||||
|
|
||||||
|
import com.kamco.cd.kamcoback.common.utils.enums.EnumType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum GukYuinStatus implements EnumType {
|
||||||
|
PENDING("대기"),
|
||||||
|
IN_PROGRESS("사용"),
|
||||||
|
COMPLETED("완료");
|
||||||
|
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return name();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText() {
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
package com.kamco.cd.kamcoback.gukyuin.service;
|
||||||
|
|
||||||
|
import com.kamco.cd.kamcoback.common.utils.NetUtils;
|
||||||
|
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient;
|
||||||
|
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult;
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto;
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.dto.ChngDetectMastDto.ResReturn;
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFacts;
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFailCode;
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkableRes;
|
||||||
|
import com.kamco.cd.kamcoback.postgres.core.GukYuinCoreService;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class GukYuinApiService {
|
||||||
|
|
||||||
|
@Value("${spring.profiles.active:local}")
|
||||||
|
private String profile;
|
||||||
|
|
||||||
|
@Value("${gukyuin.url}")
|
||||||
|
private String gukyuinUrl;
|
||||||
|
|
||||||
|
@Value("${gukyuin.mast}")
|
||||||
|
private String gukyuinMastUrl;
|
||||||
|
|
||||||
|
private final GukYuinCoreService gukyuinCoreService;
|
||||||
|
private final ExternalHttpClient externalHttpClient;
|
||||||
|
private final NetUtils netUtils = new NetUtils();
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public ChngDetectMastDto.Basic regist(ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) {
|
||||||
|
|
||||||
|
ChngDetectMastDto.Basic basic = new ChngDetectMastDto.Basic();
|
||||||
|
|
||||||
|
String url = gukyuinMastUrl + "/regist";
|
||||||
|
// url = "http://localhost:8080/api/kcd/cdi/detect/mast/regist";
|
||||||
|
|
||||||
|
String myip = netUtils.getLocalIP();
|
||||||
|
chnDetectMastReq.setReqIp(myip);
|
||||||
|
|
||||||
|
System.out.println("url == " + url);
|
||||||
|
System.out.println("url == " + myip);
|
||||||
|
|
||||||
|
ExternalCallResult<String> result =
|
||||||
|
externalHttpClient.call(
|
||||||
|
url, HttpMethod.POST, chnDetectMastReq, netUtils.jsonHeaders(), String.class);
|
||||||
|
|
||||||
|
System.out.println("result == " + result);
|
||||||
|
|
||||||
|
return basic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public ResReturn remove(ChngDetectMastDto.ChnDetectMastReqDto chnDetectMastReq) {
|
||||||
|
ChngDetectMastDto.Basic basic = new ChngDetectMastDto.Basic();
|
||||||
|
|
||||||
|
String url = gukyuinMastUrl + "/remove";
|
||||||
|
// url = "http://localhost:8080/api/kcd/cdi/detect/mast/remove";
|
||||||
|
|
||||||
|
String myip = netUtils.getLocalIP();
|
||||||
|
chnDetectMastReq.setReqIp(myip);
|
||||||
|
|
||||||
|
System.out.println("url == " + url);
|
||||||
|
System.out.println("url == " + myip);
|
||||||
|
|
||||||
|
ExternalCallResult<String> result =
|
||||||
|
externalHttpClient.call(
|
||||||
|
url, HttpMethod.POST, chnDetectMastReq, netUtils.jsonHeaders(), String.class);
|
||||||
|
|
||||||
|
System.out.println("result == " + result);
|
||||||
|
|
||||||
|
return new ResReturn("success", "탐지결과 삭제 되었습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public List<ChngDetectMastDto.Basic> list(ChngDetectMastDto.ChngDetectMastSearchDto searchDto) {
|
||||||
|
List<ChngDetectMastDto.Basic> masterList = new ArrayList<>();
|
||||||
|
|
||||||
|
String queryString = netUtils.dtoToQueryString(searchDto, null);
|
||||||
|
String url = gukyuinMastUrl + queryString;
|
||||||
|
|
||||||
|
ExternalCallResult<String> result =
|
||||||
|
externalHttpClient.call(url, HttpMethod.GET, null, netUtils.jsonHeaders(), String.class);
|
||||||
|
|
||||||
|
System.out.println("list result == " + result);
|
||||||
|
|
||||||
|
return masterList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 국유in연동 가능여부 확인
|
||||||
|
*
|
||||||
|
* @param uuid uuid
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GukYuinLinkableRes getIsLinkGukYuin(UUID uuid) {
|
||||||
|
GukYuinLinkFacts f = gukyuinCoreService.findLinkFacts(uuid);
|
||||||
|
GukYuinLinkFailCode code = decideCode(f);
|
||||||
|
|
||||||
|
GukYuinLinkableRes res = new GukYuinLinkableRes();
|
||||||
|
// res.setCode(code);
|
||||||
|
res.setLinkable(code == GukYuinLinkFailCode.OK);
|
||||||
|
res.setMessage(code.getDesc());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GukYuinLinkFailCode decideCode(GukYuinLinkFacts f) {
|
||||||
|
|
||||||
|
if (!f.existsLearn()) {
|
||||||
|
return GukYuinLinkFailCode.NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f.isPartScope()) {
|
||||||
|
return GukYuinLinkFailCode.SCOPE_PART_NOT_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f.hasRunningInference()) {
|
||||||
|
return GukYuinLinkFailCode.HAS_RUNNING_INFERENCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f.hasOtherUnfinishedGukYuin()) {
|
||||||
|
return GukYuinLinkFailCode.OTHER_GUKYUIN_IN_PROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GukYuinLinkFailCode.OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -204,80 +204,6 @@ public class InferenceResultApiController {
|
|||||||
return ApiResponseDto.ok(result);
|
return ApiResponseDto.ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ApiResponses(
|
|
||||||
// value = {
|
|
||||||
// @ApiResponse(
|
|
||||||
// responseCode = "200",
|
|
||||||
// description = "검색 성공",
|
|
||||||
// content =
|
|
||||||
// @Content(
|
|
||||||
// mediaType = "application/json",
|
|
||||||
// schema = @Schema(implementation = InferenceDetailDto.AnalResSummary.class))),
|
|
||||||
// @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
|
||||||
// @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
|
||||||
// })
|
|
||||||
// @GetMapping("/summary/{id}")
|
|
||||||
// public ApiResponseDto<InferenceDetailDto.AnalResSummary> getInferenceResultSummary(
|
|
||||||
// @Parameter(description = "목록 id", example = "53") @PathVariable Long id) {
|
|
||||||
// return ApiResponseDto.ok(inferenceResultService.getInferenceResultSummary(id));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Operation(summary = "추론관리 분석결과 상세", description = "분석결과 상제 정보 Summary, DashBoard")
|
|
||||||
// @ApiResponses(
|
|
||||||
// value = {
|
|
||||||
// @ApiResponse(
|
|
||||||
// responseCode = "200",
|
|
||||||
// description = "검색 성공",
|
|
||||||
// content =
|
|
||||||
// @Content(
|
|
||||||
// mediaType = "application/json",
|
|
||||||
// schema = @Schema(implementation = InferenceDetailDto.Detail.class))),
|
|
||||||
// @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
|
||||||
// @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
|
||||||
// })
|
|
||||||
// @GetMapping("/detail/{id}")
|
|
||||||
// public ApiResponseDto<InferenceDetailDto.Detail> getInferenceDetail(
|
|
||||||
// @Parameter(description = "목록 id", example = "53") @PathVariable Long id) {
|
|
||||||
// return ApiResponseDto.ok(inferenceResultService.getDetail(id));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Operation(summary = "추론관리 분석결과 상세 목록", description = "추론관리 분석결과 상세 목록 geojson 데이터 조회")
|
|
||||||
// @ApiResponses(
|
|
||||||
// value = {
|
|
||||||
// @ApiResponse(
|
|
||||||
// responseCode = "200",
|
|
||||||
// description = "검색 성공",
|
|
||||||
// content =
|
|
||||||
// @Content(
|
|
||||||
// mediaType = "application/json",
|
|
||||||
// schema = @Schema(implementation = Page.class))),
|
|
||||||
// @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
|
||||||
// @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
|
||||||
// })
|
|
||||||
// @GetMapping("/geom/{id}")
|
|
||||||
// public ApiResponseDto<Page<InferenceDetailDto.Geom>> getInferenceResultGeomList(
|
|
||||||
// @Parameter(description = "분석결과 id", example = "53") @PathVariable Long id,
|
|
||||||
// @Parameter(description = "기준년도 분류", example = "land") @RequestParam(required = false)
|
|
||||||
// String targetClass,
|
|
||||||
// @Parameter(description = "비교년도 분류", example = "waste") @RequestParam(required = false)
|
|
||||||
// String compareClass,
|
|
||||||
// @Parameter(description = "5000:1 도협번호 37801011,37801012") @RequestParam(required = false)
|
|
||||||
// List<Long> mapSheetNum,
|
|
||||||
// @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0")
|
|
||||||
// int page,
|
|
||||||
// @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20")
|
|
||||||
// int size,
|
|
||||||
// @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc")
|
|
||||||
// @RequestParam(required = false)
|
|
||||||
// String sort) {
|
|
||||||
// InferenceDetailDto.SearchGeoReq searchGeoReq =
|
|
||||||
// new InferenceDetailDto.SearchGeoReq(
|
|
||||||
// targetClass, compareClass, mapSheetNum, page, size, sort);
|
|
||||||
// Page<InferenceDetailDto.Geom> geomList =
|
|
||||||
// inferenceResultService.getInferenceResultGeomList(id, searchGeoReq);
|
|
||||||
// return ApiResponseDto.ok(geomList);
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Operation(summary = "추론관리 추론진행 서버 현황", description = "추론관리 추론진행 서버 현황")
|
@Operation(summary = "추론관리 추론진행 서버 현황", description = "추론관리 추론진행 서버 현황")
|
||||||
@ApiResponses(
|
@ApiResponses(
|
||||||
value = {
|
value = {
|
||||||
@@ -336,7 +262,7 @@ public class InferenceResultApiController {
|
|||||||
})
|
})
|
||||||
@GetMapping("/infer-result-info")
|
@GetMapping("/infer-result-info")
|
||||||
public ApiResponseDto<InferenceDetailDto.AnalResultInfo> getInferenceResultInfo(
|
public ApiResponseDto<InferenceDetailDto.AnalResultInfo> getInferenceResultInfo(
|
||||||
@Parameter(description = "회차 uuid", example = "f30e8817-9625-4fff-ba43-c1e6ed2067c4")
|
@Parameter(description = "회차 uuid", example = "5799eb21-4780-48b0-a82e-e58dcbb8806b")
|
||||||
@RequestParam
|
@RequestParam
|
||||||
UUID uuid) {
|
UUID uuid) {
|
||||||
return ApiResponseDto.ok(inferenceResultService.getInferenceResultInfo(uuid));
|
return ApiResponseDto.ok(inferenceResultService.getInferenceResultInfo(uuid));
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package com.kamco.cd.kamcoback.inference.dto;
|
|||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.kamco.cd.kamcoback.common.enums.DetectionClassification;
|
import com.kamco.cd.kamcoback.common.enums.DetectionClassification;
|
||||||
import com.kamco.cd.kamcoback.common.enums.ImageryFitStatus;
|
import com.kamco.cd.kamcoback.common.enums.ImageryFitStatus;
|
||||||
import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm;
|
import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm;
|
||||||
@@ -308,16 +311,16 @@ public class InferenceDetailDto {
|
|||||||
String mapSheetName;
|
String mapSheetName;
|
||||||
String subUid;
|
String subUid;
|
||||||
String pnu;
|
String pnu;
|
||||||
String passYn;
|
String fitState;
|
||||||
|
|
||||||
@JsonProperty("passYn")
|
@JsonProperty("fitState")
|
||||||
public String getPassYn() {
|
public String getFitState() {
|
||||||
return this.passYn == null ? null : this.passYn;
|
return this.fitState == null ? null : this.fitState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonProperty("passYnName")
|
@JsonProperty("fitStateName")
|
||||||
public String getPassYnName() {
|
public String fitStateName() {
|
||||||
return ImageryFitStatus.getDescByCode(this.passYn);
|
return ImageryFitStatus.getDescByCode(this.fitState);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @JsonIgnore String gemoStr;
|
// @JsonIgnore String gemoStr;
|
||||||
@@ -339,7 +342,7 @@ public class InferenceDetailDto {
|
|||||||
String mapSheetName,
|
String mapSheetName,
|
||||||
String subUid,
|
String subUid,
|
||||||
String pnu,
|
String pnu,
|
||||||
String passYn) {
|
String fitState) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.uid = uid;
|
this.uid = uid;
|
||||||
this.compareYyyy = compareYyyy;
|
this.compareYyyy = compareYyyy;
|
||||||
@@ -355,7 +358,7 @@ public class InferenceDetailDto {
|
|||||||
this.mapSheetName = mapSheetName;
|
this.mapSheetName = mapSheetName;
|
||||||
this.subUid = subUid;
|
this.subUid = subUid;
|
||||||
this.pnu = pnu;
|
this.pnu = pnu;
|
||||||
this.passYn = passYn;
|
this.fitState = fitState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,6 +434,7 @@ public class InferenceDetailDto {
|
|||||||
|
|
||||||
@Schema(name = "AnalResultInfo", description = "추론결과 기본정보")
|
@Schema(name = "AnalResultInfo", description = "추론결과 기본정보")
|
||||||
@Getter
|
@Getter
|
||||||
|
@Setter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public static class AnalResultInfo {
|
public static class AnalResultInfo {
|
||||||
@@ -448,6 +452,31 @@ public class InferenceDetailDto {
|
|||||||
private Integer stage;
|
private Integer stage;
|
||||||
private String elapsedDuration;
|
private String elapsedDuration;
|
||||||
private String subUid;
|
private String subUid;
|
||||||
|
private Boolean applyYn;
|
||||||
|
@JsonFormatDttm private ZonedDateTime applyDttm;
|
||||||
|
|
||||||
|
private String bboxGeom;
|
||||||
|
private String bboxCenterPoint;
|
||||||
|
|
||||||
|
@JsonProperty("bboxGeom")
|
||||||
|
public JsonNode getBboxGeom() {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
try {
|
||||||
|
return mapper.readTree(this.bboxGeom);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty("bboxCenterPoint")
|
||||||
|
public JsonNode getBboxCenterPoint() {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
try {
|
||||||
|
return mapper.readTree(this.bboxCenterPoint);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public AnalResultInfo(
|
public AnalResultInfo(
|
||||||
String analTitle,
|
String analTitle,
|
||||||
@@ -461,7 +490,9 @@ public class InferenceDetailDto {
|
|||||||
ZonedDateTime inferStartDttm,
|
ZonedDateTime inferStartDttm,
|
||||||
ZonedDateTime inferEndDttm,
|
ZonedDateTime inferEndDttm,
|
||||||
Integer stage,
|
Integer stage,
|
||||||
String subUid) {
|
String subUid,
|
||||||
|
Boolean applyYn,
|
||||||
|
ZonedDateTime applyDttm) {
|
||||||
this.analTitle = analTitle;
|
this.analTitle = analTitle;
|
||||||
this.modelVer1 = modelVer1;
|
this.modelVer1 = modelVer1;
|
||||||
this.modelVer2 = modelVer2;
|
this.modelVer2 = modelVer2;
|
||||||
@@ -474,6 +505,8 @@ public class InferenceDetailDto {
|
|||||||
this.inferEndDttm = inferEndDttm;
|
this.inferEndDttm = inferEndDttm;
|
||||||
this.stage = stage;
|
this.stage = stage;
|
||||||
this.subUid = subUid;
|
this.subUid = subUid;
|
||||||
|
this.applyYn = applyYn;
|
||||||
|
this.applyDttm = applyDttm;
|
||||||
Duration elapsed =
|
Duration elapsed =
|
||||||
(inferStartDttm != null && inferEndDttm != null)
|
(inferStartDttm != null && inferEndDttm != null)
|
||||||
? Duration.between(inferStartDttm, inferEndDttm)
|
? Duration.between(inferStartDttm, inferEndDttm)
|
||||||
@@ -492,6 +525,16 @@ public class InferenceDetailDto {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class BboxPointDto {
|
||||||
|
|
||||||
|
private String bboxGeom;
|
||||||
|
private String bboxCenterPoint;
|
||||||
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
|||||||
@@ -574,6 +574,12 @@ public class InferenceResultService {
|
|||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 추론결과 기본정보
|
||||||
|
*
|
||||||
|
* @param uuid uuid
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public AnalResultInfo getInferenceResultInfo(UUID uuid) {
|
public AnalResultInfo getInferenceResultInfo(UUID uuid) {
|
||||||
return inferenceResultCoreService.getInferenceResultInfo(uuid);
|
return inferenceResultCoreService.getInferenceResultInfo(uuid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,27 @@ import lombok.Getter;
|
|||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum EventType implements EnumType {
|
public enum EventType implements EnumType {
|
||||||
CREATE("생성"),
|
LIST("목록"),
|
||||||
READ("조회"),
|
DETAIL("상세"),
|
||||||
UPDATE("수정"),
|
POPUP("팝업"),
|
||||||
DELETE("삭제"),
|
STATUS("상태"),
|
||||||
|
ADDED("추가"),
|
||||||
|
MODIFIED("수정"),
|
||||||
|
REMOVE("삭제"),
|
||||||
DOWNLOAD("다운로드"),
|
DOWNLOAD("다운로드"),
|
||||||
PRINT("출력"),
|
LOGIN("로그인"),
|
||||||
OTHER("기타");
|
OTHER("기타");
|
||||||
|
|
||||||
private final String desc;
|
private final String desc;
|
||||||
|
|
||||||
|
public static EventType fromName(String name) {
|
||||||
|
try {
|
||||||
|
return EventType.valueOf(name.toUpperCase());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return name();
|
return name();
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.kamco.cd.kamcoback.postgres.core;
|
||||||
|
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFacts;
|
||||||
|
import com.kamco.cd.kamcoback.postgres.repository.Inference.MapSheetLearnRepository;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class GukYuinCoreService {
|
||||||
|
|
||||||
|
private final MapSheetLearnRepository mapSheetLearnRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 국유in연동 가능여부 확인
|
||||||
|
*
|
||||||
|
* @param uuid uuid
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GukYuinLinkFacts findLinkFacts(UUID uuid) {
|
||||||
|
return mapSheetLearnRepository.findLinkFacts(uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
|||||||
import com.kamco.cd.kamcoback.common.utils.UserUtil;
|
import com.kamco.cd.kamcoback.common.utils.UserUtil;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.AnalResultInfo;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.AnalResultInfo;
|
||||||
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.BboxPointDto;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Geom;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Geom;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.InferenceBatchSheet;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.InferenceBatchSheet;
|
||||||
@@ -409,8 +410,18 @@ public class InferenceResultCoreService {
|
|||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 추론결과 기본정보
|
||||||
|
*
|
||||||
|
* @param uuid uuid
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public AnalResultInfo getInferenceResultInfo(UUID uuid) {
|
public AnalResultInfo getInferenceResultInfo(UUID uuid) {
|
||||||
return mapSheetLearnRepository.getInferenceResultInfo(uuid);
|
AnalResultInfo resultInfo = mapSheetLearnRepository.getInferenceResultInfo(uuid);
|
||||||
|
BboxPointDto bboxPointDto = mapSheetLearnRepository.getBboxPoint(uuid);
|
||||||
|
resultInfo.setBboxGeom(bboxPointDto.getBboxGeom());
|
||||||
|
resultInfo.setBboxCenterPoint(bboxPointDto.getBboxCenterPoint());
|
||||||
|
return resultInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Dashboard> getInferenceClassCountList(UUID uuid) {
|
public List<Dashboard> getInferenceClassCountList(UUID uuid) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import jakarta.persistence.GeneratedValue;
|
|||||||
import jakarta.persistence.GenerationType;
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
import java.util.UUID;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@@ -51,6 +52,12 @@ public class AuditLogEntity extends CommonCreateEntity {
|
|||||||
@Column(name = "error_log_uid")
|
@Column(name = "error_log_uid")
|
||||||
private Long errorLogUid;
|
private Long errorLogUid;
|
||||||
|
|
||||||
|
@Column(name = "download_uuid")
|
||||||
|
private UUID downloadUuid;
|
||||||
|
|
||||||
|
@Column(name = "login_attempt_id")
|
||||||
|
private String loginAttemptId;
|
||||||
|
|
||||||
public AuditLogEntity(
|
public AuditLogEntity(
|
||||||
Long userUid,
|
Long userUid,
|
||||||
EventType eventType,
|
EventType eventType,
|
||||||
@@ -59,7 +66,9 @@ public class AuditLogEntity extends CommonCreateEntity {
|
|||||||
String ipAddress,
|
String ipAddress,
|
||||||
String requestUri,
|
String requestUri,
|
||||||
String requestBody,
|
String requestBody,
|
||||||
Long errorLogUid) {
|
Long errorLogUid,
|
||||||
|
UUID downloadUuid,
|
||||||
|
String loginAttemptId) {
|
||||||
this.userUid = userUid;
|
this.userUid = userUid;
|
||||||
this.eventType = eventType;
|
this.eventType = eventType;
|
||||||
this.eventStatus = eventStatus;
|
this.eventStatus = eventStatus;
|
||||||
@@ -68,11 +77,18 @@ public class AuditLogEntity extends CommonCreateEntity {
|
|||||||
this.requestUri = requestUri;
|
this.requestUri = requestUri;
|
||||||
this.requestBody = requestBody;
|
this.requestBody = requestBody;
|
||||||
this.errorLogUid = errorLogUid;
|
this.errorLogUid = errorLogUid;
|
||||||
|
this.downloadUuid = downloadUuid;
|
||||||
|
this.loginAttemptId = loginAttemptId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 파일 다운로드 이력 생성 */
|
/** 파일 다운로드 이력 생성 */
|
||||||
public static AuditLogEntity forFileDownload(
|
public static AuditLogEntity forFileDownload(
|
||||||
Long userId, String requestUri, String menuUid, String ip, int httpStatus) {
|
Long userId,
|
||||||
|
String requestUri,
|
||||||
|
String menuUid,
|
||||||
|
String ip,
|
||||||
|
int httpStatus,
|
||||||
|
UUID downloadUuid) {
|
||||||
|
|
||||||
return new AuditLogEntity(
|
return new AuditLogEntity(
|
||||||
userId,
|
userId,
|
||||||
@@ -82,7 +98,9 @@ public class AuditLogEntity extends CommonCreateEntity {
|
|||||||
ip,
|
ip,
|
||||||
requestUri,
|
requestUri,
|
||||||
null, // requestBody 없음
|
null, // requestBody 없음
|
||||||
null // errorLogUid 없음
|
null, // errorLogUid 없음
|
||||||
|
downloadUuid,
|
||||||
|
null // loginAttemptId 없음
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ public class MapSheetAnalDataInferenceGeomEntity {
|
|||||||
private Long pnu;
|
private Long pnu;
|
||||||
|
|
||||||
@Size(max = 20)
|
@Size(max = 20)
|
||||||
@ColumnDefault("'0'")
|
|
||||||
@Column(name = "fit_state", length = 20)
|
@Column(name = "fit_state", length = 20)
|
||||||
private String fitState;
|
private String fitState;
|
||||||
|
|
||||||
@@ -150,12 +149,6 @@ public class MapSheetAnalDataInferenceGeomEntity {
|
|||||||
@Column(name = "file_created_dttm")
|
@Column(name = "file_created_dttm")
|
||||||
private ZonedDateTime fileCreatedDttm;
|
private ZonedDateTime fileCreatedDttm;
|
||||||
|
|
||||||
@Column(name = "pass_yn")
|
|
||||||
private String passYn;
|
|
||||||
|
|
||||||
@Column(name = "pass_yn_dttm")
|
|
||||||
private ZonedDateTime passYnDttm;
|
|
||||||
|
|
||||||
@Column(name = "result_uid")
|
@Column(name = "result_uid")
|
||||||
private String resultUid;
|
private String resultUid;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.kamco.cd.kamcoback.postgres.entity;
|
package com.kamco.cd.kamcoback.postgres.entity;
|
||||||
|
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
@@ -186,6 +187,12 @@ public class MapSheetLearnEntity {
|
|||||||
@Column(name = "m3_failed_jobs", nullable = false)
|
@Column(name = "m3_failed_jobs", nullable = false)
|
||||||
private int m3FailedJobs = 0;
|
private int m3FailedJobs = 0;
|
||||||
|
|
||||||
|
@Column(name = "apply_status")
|
||||||
|
private String applyStatus = GukYuinStatus.PENDING.getId();
|
||||||
|
|
||||||
|
@Column(name = "apply_status_dttm")
|
||||||
|
private ZonedDateTime applyStatusDttm;
|
||||||
|
|
||||||
@Column(name = "uid", nullable = false)
|
@Column(name = "uid", nullable = false)
|
||||||
private String uid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
|
private String uid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.kamco.cd.kamcoback.postgres.repository.Inference;
|
package com.kamco.cd.kamcoback.postgres.repository.Inference;
|
||||||
|
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFacts;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.AnalResultInfo;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.AnalResultInfo;
|
||||||
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.BboxPointDto;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Geom;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Geom;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.SearchGeoReq;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.SearchGeoReq;
|
||||||
@@ -34,7 +36,11 @@ public interface MapSheetLearnRepositoryCustom {
|
|||||||
|
|
||||||
AnalResultInfo getInferenceResultInfo(UUID uuid);
|
AnalResultInfo getInferenceResultInfo(UUID uuid);
|
||||||
|
|
||||||
|
BboxPointDto getBboxPoint(UUID uuid);
|
||||||
|
|
||||||
List<Dashboard> getInferenceClassCountList(UUID uuid);
|
List<Dashboard> getInferenceClassCountList(UUID uuid);
|
||||||
|
|
||||||
Page<Geom> getInferenceGeomList(UUID uuid, SearchGeoReq searchGeoReq);
|
Page<Geom> getInferenceGeomList(UUID uuid, SearchGeoReq searchGeoReq);
|
||||||
|
|
||||||
|
GukYuinLinkFacts findLinkFacts(UUID uuid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ import static com.kamco.cd.kamcoback.postgres.entity.QSystemMetricEntity.systemM
|
|||||||
|
|
||||||
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
||||||
import com.kamco.cd.kamcoback.common.utils.DateRange;
|
import com.kamco.cd.kamcoback.common.utils.DateRange;
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinDto.GukYuinLinkFacts;
|
||||||
|
import com.kamco.cd.kamcoback.gukyuin.dto.GukYuinStatus;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.AnalResultInfo;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.AnalResultInfo;
|
||||||
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.BboxPointDto;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Geom;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Geom;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.SearchGeoReq;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.SearchGeoReq;
|
||||||
@@ -20,10 +23,14 @@ import com.kamco.cd.kamcoback.inference.dto.InferenceProgressDto;
|
|||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceServerStatusDto;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceServerStatusDto;
|
||||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceStatusDetailDto;
|
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceStatusDetailDto;
|
||||||
|
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheetScope;
|
||||||
import com.kamco.cd.kamcoback.model.service.ModelMngService;
|
import com.kamco.cd.kamcoback.model.service.ModelMngService;
|
||||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnEntity;
|
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnEntity;
|
||||||
|
import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalInferenceEntity;
|
||||||
|
import com.kamco.cd.kamcoback.postgres.entity.QMapSheetLearnEntity;
|
||||||
import com.kamco.cd.kamcoback.postgres.entity.QModelMngEntity;
|
import com.kamco.cd.kamcoback.postgres.entity.QModelMngEntity;
|
||||||
import com.querydsl.core.BooleanBuilder;
|
import com.querydsl.core.BooleanBuilder;
|
||||||
|
import com.querydsl.core.types.Expression;
|
||||||
import com.querydsl.core.types.Projections;
|
import com.querydsl.core.types.Projections;
|
||||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
import com.querydsl.core.types.dsl.BooleanExpression;
|
||||||
import com.querydsl.core.types.dsl.CaseBuilder;
|
import com.querydsl.core.types.dsl.CaseBuilder;
|
||||||
@@ -319,7 +326,9 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
|
|||||||
mapSheetLearnEntity.inferStartDttm,
|
mapSheetLearnEntity.inferStartDttm,
|
||||||
mapSheetLearnEntity.inferEndDttm,
|
mapSheetLearnEntity.inferEndDttm,
|
||||||
mapSheetLearnEntity.stage,
|
mapSheetLearnEntity.stage,
|
||||||
Expressions.stringTemplate("substring({0} from 1 for 8)", mapSheetLearnEntity.uid)))
|
Expressions.stringTemplate("substring({0} from 1 for 8)", mapSheetLearnEntity.uid),
|
||||||
|
mapSheetLearnEntity.applyYn,
|
||||||
|
mapSheetLearnEntity.applyDttm))
|
||||||
.from(mapSheetLearnEntity)
|
.from(mapSheetLearnEntity)
|
||||||
.leftJoin(m1)
|
.leftJoin(m1)
|
||||||
.on(mapSheetLearnEntity.m1ModelUuid.eq(m1.uuid))
|
.on(mapSheetLearnEntity.m1ModelUuid.eq(m1.uuid))
|
||||||
@@ -331,6 +340,30 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
|
|||||||
.fetchOne();
|
.fetchOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BboxPointDto getBboxPoint(UUID uuid) {
|
||||||
|
Expression<String> bboxGeom =
|
||||||
|
Expressions.stringTemplate(
|
||||||
|
"ST_AsGeoJSON(ST_Envelope(ST_Collect({0})))", mapSheetAnalDataInferenceGeomEntity.geom);
|
||||||
|
|
||||||
|
Expression<String> bboxCenterPoint =
|
||||||
|
Expressions.stringTemplate(
|
||||||
|
"ST_AsGeoJSON(ST_Centroid(ST_Envelope(ST_Collect({0}))))",
|
||||||
|
mapSheetAnalDataInferenceGeomEntity.geom);
|
||||||
|
|
||||||
|
return queryFactory
|
||||||
|
.select(Projections.constructor(BboxPointDto.class, bboxGeom, bboxCenterPoint))
|
||||||
|
.from(mapSheetLearnEntity)
|
||||||
|
.join(mapSheetAnalInferenceEntity)
|
||||||
|
.on(mapSheetAnalInferenceEntity.learnId.eq(mapSheetLearnEntity.id))
|
||||||
|
.join(mapSheetAnalDataInferenceEntity)
|
||||||
|
.on(mapSheetAnalDataInferenceEntity.analUid.eq(mapSheetAnalInferenceEntity.id))
|
||||||
|
.join(mapSheetAnalDataInferenceGeomEntity)
|
||||||
|
.on(mapSheetAnalDataInferenceGeomEntity.dataUid.eq(mapSheetAnalDataInferenceEntity.id))
|
||||||
|
.where(mapSheetLearnEntity.uuid.eq(uuid))
|
||||||
|
.fetchOne();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Dashboard> getInferenceClassCountList(UUID uuid) {
|
public List<Dashboard> getInferenceClassCountList(UUID uuid) {
|
||||||
|
|
||||||
@@ -420,7 +453,7 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
|
|||||||
|
|
||||||
StringExpression pnu =
|
StringExpression pnu =
|
||||||
Expressions.stringTemplate(
|
Expressions.stringTemplate(
|
||||||
"coalesce(({0}), '')",
|
"nullif(({0}), '')",
|
||||||
JPAExpressions.select(Expressions.stringTemplate("string_agg({0}, ',')", pnuEntity.pnu))
|
JPAExpressions.select(Expressions.stringTemplate("string_agg({0}, ',')", pnuEntity.pnu))
|
||||||
.from(pnuEntity)
|
.from(pnuEntity)
|
||||||
.where(pnuEntity.geo.geoUid.eq(mapSheetAnalDataInferenceGeomEntity.geoUid)));
|
.where(pnuEntity.geo.geoUid.eq(mapSheetAnalDataInferenceGeomEntity.geoUid)));
|
||||||
@@ -446,7 +479,7 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
|
|||||||
"substring({0} from 1 for 8)",
|
"substring({0} from 1 for 8)",
|
||||||
mapSheetAnalDataInferenceGeomEntity.resultUid),
|
mapSheetAnalDataInferenceGeomEntity.resultUid),
|
||||||
pnu,
|
pnu,
|
||||||
mapSheetAnalDataInferenceGeomEntity.passYn))
|
mapSheetAnalDataInferenceGeomEntity.fitState))
|
||||||
.from(mapSheetAnalInferenceEntity)
|
.from(mapSheetAnalInferenceEntity)
|
||||||
.join(mapSheetAnalDataInferenceEntity)
|
.join(mapSheetAnalDataInferenceEntity)
|
||||||
.on(mapSheetAnalDataInferenceEntity.analUid.eq(mapSheetAnalInferenceEntity.id))
|
.on(mapSheetAnalDataInferenceEntity.analUid.eq(mapSheetAnalInferenceEntity.id))
|
||||||
@@ -474,4 +507,57 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
|
|||||||
|
|
||||||
return new PageImpl<>(content, pageable, total == null ? 0L : total);
|
return new PageImpl<>(content, pageable, total == null ? 0L : total);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 국유in연동 가능여부 확인
|
||||||
|
*
|
||||||
|
* @param uuid uuid
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public GukYuinLinkFacts findLinkFacts(UUID uuid) {
|
||||||
|
|
||||||
|
MapSheetLearnEntity learn =
|
||||||
|
queryFactory
|
||||||
|
.selectFrom(QMapSheetLearnEntity.mapSheetLearnEntity)
|
||||||
|
.where(QMapSheetLearnEntity.mapSheetLearnEntity.uuid.eq(uuid))
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
if (learn == null) {
|
||||||
|
return new GukYuinLinkFacts(false, false, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isPartScope = MapSheetScope.PART.getId().equals(learn.getMapSheetScope());
|
||||||
|
|
||||||
|
QMapSheetAnalInferenceEntity inf = QMapSheetAnalInferenceEntity.mapSheetAnalInferenceEntity;
|
||||||
|
QMapSheetLearnEntity learn2 = new QMapSheetLearnEntity("learn2");
|
||||||
|
QMapSheetLearnEntity learnQ = QMapSheetLearnEntity.mapSheetLearnEntity;
|
||||||
|
|
||||||
|
boolean hasRunningInference =
|
||||||
|
queryFactory
|
||||||
|
.selectOne()
|
||||||
|
.from(inf)
|
||||||
|
.join(learn2)
|
||||||
|
.on(inf.learnId.eq(learn2.id))
|
||||||
|
.where(
|
||||||
|
learn2.compareYyyy.eq(learn.getCompareYyyy()),
|
||||||
|
learn2.targetYyyy.eq(learn.getTargetYyyy()),
|
||||||
|
inf.analState.in("ASSIGNED", "ING"))
|
||||||
|
.fetchFirst()
|
||||||
|
!= null;
|
||||||
|
|
||||||
|
boolean hasOtherUnfinishedGukYuin =
|
||||||
|
queryFactory
|
||||||
|
.selectOne()
|
||||||
|
.from(learnQ)
|
||||||
|
.where(
|
||||||
|
learnQ.compareYyyy.eq(learn.getCompareYyyy()),
|
||||||
|
learnQ.targetYyyy.eq(learn.getTargetYyyy()),
|
||||||
|
learnQ.applyStatus.eq(GukYuinStatus.IN_PROGRESS.getId()),
|
||||||
|
learnQ.uuid.ne(learn.getUuid()))
|
||||||
|
.fetchFirst()
|
||||||
|
!= null;
|
||||||
|
|
||||||
|
return new GukYuinLinkFacts(true, isPartScope, hasRunningInference, hasOtherUnfinishedGukYuin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,10 +67,8 @@ public class ChangeDetectionRepositoryImpl extends QuerydslRepositorySupport
|
|||||||
mapSheetAnalSttcEntity.id.classAfterCd.as("classNm"), // 앞단 CoreService 에서 한글명으로 변환
|
mapSheetAnalSttcEntity.id.classAfterCd.as("classNm"), // 앞단 CoreService 에서 한글명으로 변환
|
||||||
mapSheetAnalSttcEntity.classAfterCnt.sum()))
|
mapSheetAnalSttcEntity.classAfterCnt.sum()))
|
||||||
.from(mapSheetAnalInferenceEntity)
|
.from(mapSheetAnalInferenceEntity)
|
||||||
.innerJoin(mapSheetAnalDataInferenceEntity)
|
|
||||||
.on(mapSheetAnalDataInferenceEntity.analUid.eq(mapSheetAnalInferenceEntity.id))
|
|
||||||
.innerJoin(mapSheetAnalSttcEntity)
|
.innerJoin(mapSheetAnalSttcEntity)
|
||||||
.on(mapSheetAnalSttcEntity.id.dataUid.eq(mapSheetAnalDataInferenceEntity.id))
|
.on(mapSheetAnalSttcEntity.id.analUid.eq(mapSheetAnalInferenceEntity.id))
|
||||||
.where(
|
.where(
|
||||||
mapSheetAnalInferenceEntity.uuid.eq(uuid),
|
mapSheetAnalInferenceEntity.uuid.eq(uuid),
|
||||||
mapScaleTypeSearchExpression(scale, mapSheetNum))
|
mapScaleTypeSearchExpression(scale, mapSheetNum))
|
||||||
|
|||||||
@@ -1152,7 +1152,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
|||||||
// 날짜별 전체 건수
|
// 날짜별 전체 건수
|
||||||
Expression<Long> dailyTotalCnt = Expressions.numberTemplate(Long.class, "COUNT(*)");
|
Expression<Long> dailyTotalCnt = Expressions.numberTemplate(Long.class, "COUNT(*)");
|
||||||
|
|
||||||
// ⭐ 전체 기간 총 건수 (윈도우 함수)
|
// 전체 기간 총 건수 (윈도우 함수)
|
||||||
Expression<Long> totalCnt = Expressions.numberTemplate(Long.class, "SUM(COUNT(*)) OVER ()");
|
Expression<Long> totalCnt = Expressions.numberTemplate(Long.class, "SUM(COUNT(*)) OVER ()");
|
||||||
|
|
||||||
// 상태별 카운트 (Postgres FILTER 사용)
|
// 상태별 카운트 (Postgres FILTER 사용)
|
||||||
@@ -1192,7 +1192,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
|||||||
LabelingStatDto.class,
|
LabelingStatDto.class,
|
||||||
workDate,
|
workDate,
|
||||||
dailyTotalCnt,
|
dailyTotalCnt,
|
||||||
totalCnt, // ⭐ 전체 일자 배정 건수
|
totalCnt, // 전체 일자 배정 건수
|
||||||
assignedCnt,
|
assignedCnt,
|
||||||
skipCnt,
|
skipCnt,
|
||||||
completeCnt,
|
completeCnt,
|
||||||
@@ -1233,7 +1233,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
|||||||
// 날짜별 전체 건수
|
// 날짜별 전체 건수
|
||||||
Expression<Long> dailyTotalCnt = Expressions.numberTemplate(Long.class, "COUNT(*)");
|
Expression<Long> dailyTotalCnt = Expressions.numberTemplate(Long.class, "COUNT(*)");
|
||||||
|
|
||||||
// ⭐ 전체 기간 총 건수 (윈도우 함수)
|
// 전체 기간 총 건수 (윈도우 함수)
|
||||||
Expression<Long> totalCnt = Expressions.numberTemplate(Long.class, "SUM(COUNT(*)) OVER ()");
|
Expression<Long> totalCnt = Expressions.numberTemplate(Long.class, "SUM(COUNT(*)) OVER ()");
|
||||||
|
|
||||||
// 상태별 카운트 (Postgres FILTER 사용)
|
// 상태별 카운트 (Postgres FILTER 사용)
|
||||||
@@ -1277,7 +1277,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
|||||||
LabelingStatDto.class,
|
LabelingStatDto.class,
|
||||||
workDate,
|
workDate,
|
||||||
dailyTotalCnt,
|
dailyTotalCnt,
|
||||||
totalCnt, // ⭐ 전체 일자 배정 건수
|
totalCnt, // 전체 일자 배정 건수
|
||||||
assignedCnt,
|
assignedCnt,
|
||||||
skipCnt,
|
skipCnt,
|
||||||
completeCnt,
|
completeCnt,
|
||||||
|
|||||||
@@ -488,7 +488,7 @@ public class AuditLogRepositoryImpl extends QuerydslRepositorySupport
|
|||||||
|
|
||||||
private NumberExpression<Integer> readCount() {
|
private NumberExpression<Integer> readCount() {
|
||||||
return new CaseBuilder()
|
return new CaseBuilder()
|
||||||
.when(auditLogEntity.eventType.eq(EventType.READ))
|
.when(auditLogEntity.eventType.in(EventType.LIST, EventType.DETAIL))
|
||||||
.then(1)
|
.then(1)
|
||||||
.otherwise(0)
|
.otherwise(0)
|
||||||
.sum();
|
.sum();
|
||||||
@@ -496,7 +496,7 @@ public class AuditLogRepositoryImpl extends QuerydslRepositorySupport
|
|||||||
|
|
||||||
private NumberExpression<Integer> cudCount() {
|
private NumberExpression<Integer> cudCount() {
|
||||||
return new CaseBuilder()
|
return new CaseBuilder()
|
||||||
.when(auditLogEntity.eventType.in(EventType.CREATE, EventType.UPDATE, EventType.DELETE))
|
.when(auditLogEntity.eventType.in(EventType.ADDED, EventType.MODIFIED, EventType.REMOVE))
|
||||||
.then(1)
|
.then(1)
|
||||||
.otherwise(0)
|
.otherwise(0)
|
||||||
.sum();
|
.sum();
|
||||||
@@ -504,7 +504,7 @@ public class AuditLogRepositoryImpl extends QuerydslRepositorySupport
|
|||||||
|
|
||||||
private NumberExpression<Integer> printCount() {
|
private NumberExpression<Integer> printCount() {
|
||||||
return new CaseBuilder()
|
return new CaseBuilder()
|
||||||
.when(auditLogEntity.eventType.eq(EventType.PRINT))
|
.when(auditLogEntity.eventType.eq(EventType.OTHER))
|
||||||
.then(1)
|
.then(1)
|
||||||
.otherwise(0)
|
.otherwise(0)
|
||||||
.sum();
|
.sum();
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport
|
|||||||
"concat({0}, substring({1}, 1, 5))",
|
"concat({0}, substring({1}, 1, 5))",
|
||||||
mapInkx5kEntity.mapidNm, mapSheetMngHstEntity.mapSheetNum),
|
mapInkx5kEntity.mapidNm, mapSheetMngHstEntity.mapSheetNum),
|
||||||
|
|
||||||
// ✅ 튜플 방지: concat으로 문자열 생성
|
// 튜플 방지: concat으로 문자열 생성
|
||||||
Expressions.stringTemplate(
|
Expressions.stringTemplate(
|
||||||
"concat('(', {0}, ',', {1}, ')')",
|
"concat('(', {0}, ',', {1}, ')')",
|
||||||
mapInkx5kEntity.mapidNm, mapSheetMngHstEntity.mapSheetNum),
|
mapInkx5kEntity.mapidNm, mapSheetMngHstEntity.mapSheetNum),
|
||||||
@@ -437,7 +437,7 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport
|
|||||||
// fid 타입 주의 (Long이면 DTO도 Long으로 맞추는 걸 추천)
|
// fid 타입 주의 (Long이면 DTO도 Long으로 맞추는 걸 추천)
|
||||||
mapInkx5kEntity.fid, // 또는 mapInkx5kEntity.fid.intValue()
|
mapInkx5kEntity.fid, // 또는 mapInkx5kEntity.fid.intValue()
|
||||||
|
|
||||||
// ✅ createdDate 말고 ZonedDateTime으로 매핑된 필드로
|
// createdDate 말고 ZonedDateTime으로 매핑된 필드로
|
||||||
mapSheetMngHstEntity.createdDate, // (예시)
|
mapSheetMngHstEntity.createdDate, // (예시)
|
||||||
mapSheetMngHstEntity.syncState,
|
mapSheetMngHstEntity.syncState,
|
||||||
mapSheetMngHstEntity.syncTfwFileName,
|
mapSheetMngHstEntity.syncTfwFileName,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ spring:
|
|||||||
|
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
||||||
|
#url: jdbc:postgresql://localhost:15432/kamco_cds
|
||||||
username: kamco_cds
|
username: kamco_cds
|
||||||
password: kamco_cds_Q!W@E#R$
|
password: kamco_cds_Q!W@E#R$
|
||||||
hikari:
|
hikari:
|
||||||
@@ -109,7 +110,7 @@ inference:
|
|||||||
geojson-dir: /kamco-nfs/requests/
|
geojson-dir: /kamco-nfs/requests/
|
||||||
jar-path: /kamco-nfs/dataset/shp_exporter-1.0.0.jar
|
jar-path: /kamco-nfs/dataset/shp_exporter-1.0.0.jar
|
||||||
|
|
||||||
innopam:
|
gukyuin:
|
||||||
#url: http://localhost:8080
|
#url: http://localhost:8080
|
||||||
url: http://192.168.2.129:5301
|
url: http://192.168.2.129:5301
|
||||||
mast : ${innopam.url}/api/kcd/cdi/chn/mast
|
mast: ${gukyuin.url}/api/kcd/cdi/chn/mast
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ spring:
|
|||||||
format_sql: true # ⚠️ 선택 - SQL 포맷팅 (가독성)
|
format_sql: true # ⚠️ 선택 - SQL 포맷팅 (가독성)
|
||||||
|
|
||||||
datasource:
|
datasource:
|
||||||
#url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
||||||
url: jdbc:postgresql://localhost:25432/kamco_cds
|
#url: jdbc:postgresql://localhost:15432/kamco_cds
|
||||||
username: kamco_cds
|
username: kamco_cds
|
||||||
password: kamco_cds_Q!W@E#R$
|
password: kamco_cds_Q!W@E#R$
|
||||||
hikari:
|
hikari:
|
||||||
@@ -25,12 +25,9 @@ spring:
|
|||||||
|
|
||||||
data:
|
data:
|
||||||
redis:
|
redis:
|
||||||
#host: 192.168.2.109
|
host: 192.168.2.109
|
||||||
#port: 6379
|
|
||||||
#password: kamco
|
|
||||||
host: localhost
|
|
||||||
port: 6379
|
port: 6379
|
||||||
password:
|
password: kamco
|
||||||
|
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
@@ -68,13 +65,13 @@ mapsheet:
|
|||||||
shp:
|
shp:
|
||||||
baseurl: /Users/bokmin/detect/result
|
baseurl: /Users/bokmin/detect/result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
file:
|
file:
|
||||||
sync-root-dir: D:/kamco-nfs/images/
|
sync-root-dir: D:/kamco-nfs/images/
|
||||||
#sync-root-dir: /kamco-nfs/images/
|
#sync-root-dir: /kamco-nfs/images/
|
||||||
sync-tmp-dir: ${file.sync-root-dir}/tmp
|
sync-tmp-dir: ${file.sync-root-dir}/tmp
|
||||||
sync-file-extention: tfw,tif
|
sync-file-extention: tfw,tif
|
||||||
sync-auto-exception-start-year: 2025
|
|
||||||
sync-auto-exception-before-year-cnt: 3
|
|
||||||
|
|
||||||
dataset-dir: D:/kamco-nfs/dataset/
|
dataset-dir: D:/kamco-nfs/dataset/
|
||||||
#dataset-dir: /kamco-nfs/dataset/export/
|
#dataset-dir: /kamco-nfs/dataset/export/
|
||||||
@@ -90,8 +87,3 @@ inference:
|
|||||||
batch-url: http://10.100.0.11:8000/batches
|
batch-url: http://10.100.0.11:8000/batches
|
||||||
geojson-dir: /kamco-nfs/requests/
|
geojson-dir: /kamco-nfs/requests/
|
||||||
jar-path: jar/makeshp-1.0.0.jar
|
jar-path: jar/makeshp-1.0.0.jar
|
||||||
|
|
||||||
innopam:
|
|
||||||
#url: http://localhost:8080
|
|
||||||
url: http://192.168.2.129:5301
|
|
||||||
mast : ${innopam.url}/api/kcd/cdi/chn/mast
|
|
||||||
|
|||||||
@@ -63,3 +63,7 @@ inference:
|
|||||||
geojson-dir: /kamco-nfs/requests/
|
geojson-dir: /kamco-nfs/requests/
|
||||||
jar-path: /kamco-nfs/dataset/shp_exporter-1.0.0.jar
|
jar-path: /kamco-nfs/dataset/shp_exporter-1.0.0.jar
|
||||||
|
|
||||||
|
gukyuin:
|
||||||
|
#url: http://localhost:8080
|
||||||
|
url: http://192.168.2.129:5301
|
||||||
|
mast: ${gukyuin.url}/api/kcd/cdi/chn/mast
|
||||||
|
|||||||
Reference in New Issue
Block a user