diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..ced6b2cd Binary files /dev/null and b/.DS_Store differ diff --git a/.ebextensions/app.config b/.ebextensions/app.config new file mode 100644 index 00000000..de8541c3 --- /dev/null +++ b/.ebextensions/app.config @@ -0,0 +1,12 @@ +files: + "/sbin/appstart" : + mode: "000755" + owner: webapp + group: webapp + content: | + #!/usr/bin/env bash + JAR_PATH=/var/app/current/application.jar + + # run app + killall java + java -Dfile.encoding=UTF-8 -jar $JAR_PATH diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 00000000..279c989c --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,54 @@ +name: Deploy to ECS + +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 17 + + - name: Build JAR + run: ./gradlew build -x test + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_REGION }} + + - name: Login to ECR + uses: aws-actions/amazon-ecr-login@v1 + + - name: Build Docker Image + run: docker build -t sero-backend . + + - name: Tag Docker Image + run: | + docker tag sero-backend:latest \ + ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/sero-backend:latest + + - name: Push Docker Image + run: | + docker push \ + ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/sero-backend:latest + + - name: Deploy to ECS + run: | + aws ecs update-service \ + --cluster sero-cluster-new \ + --service sero-task-n-service-ksz4njy2 \ + --force-new-deployment diff --git a/.platform/nginx.conf b/.platform/nginx.conf new file mode 100644 index 00000000..97070d83 --- /dev/null +++ b/.platform/nginx.conf @@ -0,0 +1,59 @@ +user nginx; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; +worker_processes auto; +worker_rlimit_nofile 33282; + +events { + use epoll; + worker_connections 1024; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + include conf.d/*.conf; + + map $http_upgrade $connection_upgrade { + default "upgrade"; + } + + upstream springboot { + server 127.0.0.1:8080; // 8080번으로 돌고 있는 백엔드 서버를 인지해라! + keepalive 1024; + } + + server { + listen 80 default_server; + listen [::]:80 default_server; + + location / { + proxy_pass http://springboot; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; // 로그분석 (어디서 유입, 차단하고 싶은 사람) + proxy_set_header X-Forwarded-Proto $scheme; + proxy_redirect off; + } + + access_log /var/log/nginx/access.log main; + + client_header_timeout 60; + client_body_timeout 60; + keepalive_timeout 60; + gzip off; + + # Include the Elastic Beanstalk generated locations + include conf.d/elasticbeanstalk/healthd.conf; + } +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..4363a8b9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM eclipse-temurin:17-jre + +WORKDIR /app + +COPY build/libs/*.jar app.jar + +EXPOSE 8080 + +ENTRYPOINT ["java", "-jar", "app.jar"] diff --git a/Procfile b/Procfile new file mode 100644 index 00000000..ae5304ad --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: java -jar application.jar \ No newline at end of file diff --git a/appspec.yml b/appspec.yml new file mode 100644 index 00000000..fedeb76c --- /dev/null +++ b/appspec.yml @@ -0,0 +1,34 @@ +version: 0.0 +os: linux +files: + - source: / + destination: /home/ec2-user/app/ + overwrite: yes + +permissions: + - object: / + pattern: "**" + owner: ec2-user + group: ec2-user + +hooks: + BeforeInstall: + - location: scripts/stop.sh + timeout: 60 + runas: ec2-user + + AfterInstall: + - location: scripts/set-permissions.sh + timeout: 60 + runas: ec2-user + + ApplicationStart: + - location: scripts/start.sh + timeout: 120 + runas: ec2-user + + # ValidateService 임시 비활성화 (디버깅용) + # ValidateService: + # - location: scripts/health-check.sh + # timeout: 180 + # runas: ec2-user diff --git a/build.gradle b/build.gradle index d3675823..f17d8d8f 100644 --- a/build.gradle +++ b/build.gradle @@ -27,10 +27,11 @@ repositories { dependencies { /* Spring boot */ implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-actuator' /* Mybatis */ implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.5' - +./gradlew clean build -x test /* JPA */ implementation 'org.springframework.boot:spring-boot-starter-data-jpa' @@ -39,8 +40,8 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' /* Database */ -// runtimeOnly 'com.mysql:mysql-connector-j' - runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' + runtimeOnly 'com.mysql:mysql-connector-j' + // runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' /* Swagger OpenAPI */ implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.14' @@ -76,4 +77,14 @@ dependencies { tasks.named('test') { useJUnitPlatform() +} + +// plain jar 생성 비활성화 (bootJar만 생성) +jar { + enabled = false +} + +// bootJar 파일명을 application.jar로 설정 +bootJar { + archiveFileName = 'application.jar' } \ No newline at end of file diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/settings.gradle b/settings.gradle index add2273e..122237cf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,4 @@ +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.10.0' +} rootProject.name = 'sero' \ No newline at end of file diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 00000000..ed67abd9 Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/main/java/com/werp/sero/HealthCheckController.java b/src/main/java/com/werp/sero/HealthCheckController.java new file mode 100644 index 00000000..2ef3c03a --- /dev/null +++ b/src/main/java/com/werp/sero/HealthCheckController.java @@ -0,0 +1,14 @@ +package com.werp.sero; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HealthCheckController { + + @GetMapping("/") + public ResponseEntity health() { + return ResponseEntity.ok("OK"); + } +} diff --git a/src/main/java/com/werp/sero/approval/command/application/controller/ApprovalCommandController.java b/src/main/java/com/werp/sero/approval/command/application/controller/ApprovalCommandController.java index 01aab9bf..1e4f4a47 100644 --- a/src/main/java/com/werp/sero/approval/command/application/controller/ApprovalCommandController.java +++ b/src/main/java/com/werp/sero/approval/command/application/controller/ApprovalCommandController.java @@ -26,7 +26,7 @@ public class ApprovalCommandController { @Operation(summary = "결재 상신") @PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) - public ResponseEntity submitForApproval(@CurrentUser final Employee employee, + public ResponseEntity submitForApproval(@CurrentUser Employee employee, @Valid @RequestPart(name = "requestDTO") final ApprovalCreateRequestDTO requestDTO, @RequestPart(name = "files", required = false) final List files) { return ResponseEntity.ok(approvalCommandService.submitForApproval(employee, requestDTO, files)); diff --git a/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandService.java b/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandService.java index e6c90066..b25f24cc 100644 --- a/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandService.java +++ b/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandService.java @@ -9,7 +9,7 @@ import java.util.List; public interface ApprovalCommandService { - ApprovalResponseDTO submitForApproval(final Employee employee, final ApprovalCreateRequestDTO requestDTO, + ApprovalResponseDTO submitForApproval(Employee employee, final ApprovalCreateRequestDTO requestDTO, final List files); void approve(final Employee employee, final int approvalId, final ApprovalDecisionRequestDTO requestDTO); diff --git a/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java b/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java index fe097c01..6bd5b33f 100644 --- a/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java +++ b/src/main/java/com/werp/sero/approval/command/application/service/ApprovalCommandServiceImpl.java @@ -53,7 +53,7 @@ public class ApprovalCommandServiceImpl implements ApprovalCommandService { @Transactional @Override - public ApprovalResponseDTO submitForApproval(final Employee employee, final ApprovalCreateRequestDTO requestDTO, + public ApprovalResponseDTO submitForApproval(Employee employee, final ApprovalCreateRequestDTO requestDTO, final List files) { validateDuplicateApproval(requestDTO.getRefCode()); diff --git a/src/main/java/com/werp/sero/common/error/exception/BusinessException.java b/src/main/java/com/werp/sero/common/error/exception/BusinessException.java index 47878bea..9ccbffd0 100644 --- a/src/main/java/com/werp/sero/common/error/exception/BusinessException.java +++ b/src/main/java/com/werp/sero/common/error/exception/BusinessException.java @@ -15,6 +15,8 @@ public BusinessException(final ErrorCode errorCode) { public BusinessException(final ErrorCode errorCode, final String message) { super(message); this.errorCode = errorCode; + + } diff --git a/src/main/java/com/werp/sero/config/AsyncConfig.java b/src/main/java/com/werp/sero/config/AsyncConfig.java index c6228c4e..e7e20917 100644 --- a/src/main/java/com/werp/sero/config/AsyncConfig.java +++ b/src/main/java/com/werp/sero/config/AsyncConfig.java @@ -7,4 +7,5 @@ @EnableAsync @Configuration public class AsyncConfig { + } \ No newline at end of file diff --git a/src/main/java/com/werp/sero/config/CorsConfig.java b/src/main/java/com/werp/sero/config/CorsConfig.java index 88b026bf..0b356872 100644 --- a/src/main/java/com/werp/sero/config/CorsConfig.java +++ b/src/main/java/com/werp/sero/config/CorsConfig.java @@ -8,13 +8,24 @@ import java.util.List; +// @Configuration public class CorsConfig { @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); - configuration.setAllowedOrigins(List.of("http://localhost:5173")); + configuration.setAllowedOrigins(List.of( + "http://localhost:5173", + "https://localhost:5173", + "http://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com", + "https://sero-f-alb-2092902385.ap-northeast-2.elb.amazonaws.com", + "https://sero-erp.cloud", + "http://sero-erp.cloud", + "http://api.sero-erp.cloud", + "https://api.sero-erp.cloud" + )); + configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); configuration.setAllowedHeaders(List.of("*")); configuration.setAllowCredentials(true); diff --git a/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java b/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java index 766b61c2..1c319be0 100644 --- a/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java +++ b/src/main/java/com/werp/sero/employee/command/domain/aggregate/Employee.java @@ -1,5 +1,6 @@ package com.werp.sero.employee.command.domain.aggregate; +import com.fasterxml.jackson.annotation.JsonIgnore; // [추가] JSON 변환 시 순환참조 방지 import jakarta.persistence.*; import lombok.Getter; import lombok.NoArgsConstructor; @@ -9,6 +10,7 @@ @NoArgsConstructor @Entity public class Employee { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @@ -43,7 +45,7 @@ public class Employee { @Column(name = "created_at", nullable = false) private String createdAt; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dept_id") private Department department; } \ No newline at end of file diff --git a/src/main/java/com/werp/sero/employee/command/domain/repository/EmployeeRepository.java b/src/main/java/com/werp/sero/employee/command/domain/repository/EmployeeRepository.java index ddfee4a0..e4a75d0a 100644 --- a/src/main/java/com/werp/sero/employee/command/domain/repository/EmployeeRepository.java +++ b/src/main/java/com/werp/sero/employee/command/domain/repository/EmployeeRepository.java @@ -2,12 +2,14 @@ import com.werp.sero.employee.command.domain.aggregate.Employee; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.util.List; import java.util.Optional; public interface EmployeeRepository extends JpaRepository { - Optional findByEmailAndStatus(final String email, final String status); + @Query("SELECT e FROM Employee e LEFT JOIN FETCH e.department WHERE e.email = :email AND e.status = :status") + Optional findByEmailAndStatusWithFetchJoin(final String email, final String status); List findByIdIn(final List employeeIds); } \ No newline at end of file diff --git a/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java b/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java index 39a74ef8..4d0f3764 100644 --- a/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java +++ b/src/main/java/com/werp/sero/material/query/dto/MaterialListResponseDTO.java @@ -22,6 +22,7 @@ public class MaterialListResponseDTO { private String status; private String baseUnit; private Long unitPrice; + private String imageUrl; private int safetyStock; private Integer cycleTime; private Integer rawMaterialCount; diff --git a/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java b/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java index 56e3389d..4961ebb0 100644 --- a/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java +++ b/src/main/java/com/werp/sero/material/query/service/MaterialQueryServiceImpl.java @@ -8,6 +8,7 @@ import com.werp.sero.material.query.dto.MaterialListResponseDTO; import com.werp.sero.material.query.dto.MaterialWithBomResponseDTO; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -17,6 +18,7 @@ /** * 자재 Query Service 구현체 (조회 전용) */ +@Slf4j @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -45,7 +47,22 @@ public List getMaterialList( } // 3. 자재 목록 조회 - return materialMapper.findByCondition(type, status, keyword); + System.out.println("===== DEBUG: Before MyBatis query ====="); + List results = materialMapper.findByCondition(type, status, keyword); + System.out.println("===== DEBUG: After MyBatis query ====="); + + // DEBUG: imageUrl 확인 + if (!results.isEmpty()) { + System.out.println("===== DEBUG: Material imageUrl check ====="); + System.out.println("First material ID: " + results.get(0).getId()); + System.out.println("First material name: " + results.get(0).getName()); + System.out.println("First material imageUrl: " + results.get(0).getImageUrl()); + System.out.println("First material spec: " + results.get(0).getSpec()); + System.out.println("First material baseUnit: " + results.get(0).getBaseUnit()); + System.out.println("=========================================="); + } + + return results; } @Override diff --git a/src/main/java/com/werp/sero/notice/command/application/controller/NoticeCommandController.java b/src/main/java/com/werp/sero/notice/command/application/controller/NoticeCommandController.java index eec5724a..2a7b44d5 100644 --- a/src/main/java/com/werp/sero/notice/command/application/controller/NoticeCommandController.java +++ b/src/main/java/com/werp/sero/notice/command/application/controller/NoticeCommandController.java @@ -25,7 +25,7 @@ public class NoticeCommandController { @Operation(summary = "공지사항 등록") @PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) - public ResponseEntity registerNotice(@CurrentUser final Employee employee, + public ResponseEntity registerNotice(@CurrentUser Employee employee, @Valid @RequestPart(name = "requestDTO") final NoticeCreateRequestDTO requestDTO, @RequestPart(name = "files", required = false) final List files) { final NoticeResponseDTO response = noticeCommandService.registerNotice(employee, requestDTO, files); diff --git a/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandService.java b/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandService.java index 119f5049..e639cf88 100644 --- a/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandService.java +++ b/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandService.java @@ -8,7 +8,7 @@ import java.util.List; public interface NoticeCommandService { - NoticeResponseDTO registerNotice(final Employee employee, final NoticeCreateRequestDTO requestDTO, + NoticeResponseDTO registerNotice(Employee employee, final NoticeCreateRequestDTO requestDTO, final List files); void deleteNotice(final Employee employee, final int noticeId); diff --git a/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java b/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java index c217c8b1..9a953b4b 100644 --- a/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java +++ b/src/main/java/com/werp/sero/notice/command/application/service/NoticeCommandServiceImpl.java @@ -41,7 +41,7 @@ public class NoticeCommandServiceImpl implements NoticeCommandService { @Transactional @Override - public NoticeResponseDTO registerNotice(final Employee employee, final NoticeCreateRequestDTO requestDTO, + public NoticeResponseDTO registerNotice(Employee employee, final NoticeCreateRequestDTO requestDTO, final List files) { validateCategory(requestDTO.getCategory()); diff --git a/src/main/java/com/werp/sero/production/command/infrastructure/service/.gitkeep b/src/main/java/com/werp/sero/production/command/infrastructure/service/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java index 289355bf..2df3ed98 100644 --- a/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java +++ b/src/main/java/com/werp/sero/security/config/ClientEmployeeSecurityConfig.java @@ -1,4 +1,4 @@ -package com.werp.sero.security.config; + package com.werp.sero.security.config; import com.werp.sero.security.handler.CustomAccessDeniedHandler; import com.werp.sero.security.handler.CustomAuthenticationEntryPoint; @@ -74,6 +74,12 @@ public SecurityFilterChain clientEmployFilterChain(final HttpSecurity http) thro ) ; + + return http.build(); } + + + + } \ No newline at end of file diff --git a/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java b/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java index 0cafdd80..2d2d67eb 100644 --- a/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java +++ b/src/main/java/com/werp/sero/security/config/EmployeeSecurityConfig.java @@ -35,6 +35,11 @@ public class EmployeeSecurityConfig { "/swagger-ui/**", "/swagger-resources/**", "/auth/login", + "/actuator/health", + "/", + "/actuator/health", // ★ AWS 로드밸런서 헬스체크용 (필수 추가) + "/actuator/**", // (선택) 다른 액추에이터 정보도 허용하려면 추가 + "/health" // (혹시 몰라 기본 경로도 추가) }; @@ -87,6 +92,7 @@ public SecurityFilterChain employeeFilterChain(final HttpSecurity http) throws E ) ; + return http.build(); } } diff --git a/src/main/java/com/werp/sero/security/service/EmployeeUserDetailsService.java b/src/main/java/com/werp/sero/security/service/EmployeeUserDetailsService.java index 6842494c..0a6c30d4 100644 --- a/src/main/java/com/werp/sero/security/service/EmployeeUserDetailsService.java +++ b/src/main/java/com/werp/sero/security/service/EmployeeUserDetailsService.java @@ -21,7 +21,7 @@ public class EmployeeUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { - final Employee employee = employeeRepository.findByEmailAndStatus(username, "ES_ACT") + final Employee employee = employeeRepository.findByEmailAndStatusWithFetchJoin(username, "ES_ACT") .orElseThrow(EmployeeNotFoundException::new); final List permissions = employeePermissionRepository.findPermissionCodeByEmployee(employee); diff --git a/src/main/java/com/werp/sero/util/CookieUtil.java b/src/main/java/com/werp/sero/util/CookieUtil.java index 3aed3edd..6b2cfbac 100644 --- a/src/main/java/com/werp/sero/util/CookieUtil.java +++ b/src/main/java/com/werp/sero/util/CookieUtil.java @@ -17,7 +17,7 @@ public void generateRefreshTokenCookie(final HttpServletResponse response, final .httpOnly(true) .sameSite("None") .path("/") - .secure(true) + .secure(true) // HTTPS 환경에서 SameSite=None은 반드시 Secure=true 필요 .maxAge(token.getExpirationTime() / 1000) .build(); @@ -29,7 +29,7 @@ public void deleteRefreshTokenCookie(final HttpServletResponse response) { .httpOnly(true) .sameSite("None") .path("/") - .secure(true) + .secure(true) // 생성 시와 동일한 설정으로 삭제해야 브라우저가 인식 .maxAge(0) .build(); diff --git a/src/main/resources/com/werp/sero/material/query/dao/BomMapper.xml b/src/main/resources/com/werp/sero/material/query/dao/BomMapper.xml index 458c3d10..19065843 100644 --- a/src/main/resources/com/werp/sero/material/query/dao/BomMapper.xml +++ b/src/main/resources/com/werp/sero/material/query/dao/BomMapper.xml @@ -17,7 +17,7 @@ - + diff --git a/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml b/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml index 301d43f4..a1bd6caf 100644 --- a/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml +++ b/src/main/resources/com/werp/sero/material/query/dao/MaterialMapper.xml @@ -13,6 +13,7 @@ + @@ -32,7 +33,7 @@ - + @@ -75,7 +76,7 @@ A.moq, A.cycle_time, A.unit_price, - A.image_url, + A.image_url AS imageUrl, A.conversion_rate, A.safety_stock, A.raw_material_count, @@ -113,7 +114,7 @@ A.moq, A.cycle_time, A.unit_price, - A.image_url, + A.image_url AS imageUrl, A.conversion_rate, A.safety_stock, A.raw_material_count, @@ -155,7 +156,7 @@ A.moq, A.cycle_time, A.unit_price, - A.image_url, + A.image_url AS imageUrl, A.conversion_rate, A.safety_stock, A.raw_material_count,