diff --git a/src/main/java/com/mfsys/uco/controller/UserController.java b/src/main/java/com/mfsys/uco/controller/UserController.java index b459541..73f093e 100644 --- a/src/main/java/com/mfsys/uco/controller/UserController.java +++ b/src/main/java/com/mfsys/uco/controller/UserController.java @@ -15,6 +15,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import java.io.ByteArrayOutputStream; import java.util.ArrayList; @@ -162,8 +163,11 @@ public class UserController { } @PostMapping(UCOURI.UPDATE_CUSTOMER_PROFILE) - public ResponseEntity updateCustomerProfile(@RequestBody UpdateProfileRequestPayload updateProfileRequestPayload) { - customerProfileService.updateCustomerProfile(updateProfileRequestPayload); + public ResponseEntity updateCustomerProfile( + @RequestParam("porOrgacode") String porOrgacode, + @RequestParam("cmpCustcode") String cmpCustcode, + @RequestParam("image") MultipartFile image) { + customerProfileService.updateCustomerProfile(porOrgacode, cmpCustcode, image); return ResponseEntity.ok(HttpStatus.OK); } @PostMapping(UCOURI.ADD_BENEFICIARY) diff --git a/src/main/java/com/mfsys/uco/dto/UpdateProfileRequestPayload.java b/src/main/java/com/mfsys/uco/dto/UpdateProfileRequestPayload.java index 78845a5..10f45fe 100644 --- a/src/main/java/com/mfsys/uco/dto/UpdateProfileRequestPayload.java +++ b/src/main/java/com/mfsys/uco/dto/UpdateProfileRequestPayload.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; @Data @Builder @@ -12,5 +13,5 @@ import lombok.NoArgsConstructor; public class UpdateProfileRequestPayload { private String porOrgacode; private String cmpCustcode; - private String cmpCustImage; + private MultipartFile image; } diff --git a/src/main/java/com/mfsys/uco/model/CustomerProfile.java b/src/main/java/com/mfsys/uco/model/CustomerProfile.java index b623f15..d558029 100644 --- a/src/main/java/com/mfsys/uco/model/CustomerProfile.java +++ b/src/main/java/com/mfsys/uco/model/CustomerProfile.java @@ -55,9 +55,7 @@ public class CustomerProfile { @Column(name = "CMP_ADDRESS", nullable = true, columnDefinition = FieldNameLength.DESCRIPTION_LONG) private String cmpAddress; - @Lob - @JsonIgnore - @Column(name = "CMP_CUSTIMG", nullable = true, columnDefinition = "LONGTEXT") + @Column(name = "CMP_CUSTIMG", nullable = true, columnDefinition = "VARCHAR(500)") private String cmpCustImage; } diff --git a/src/main/java/com/mfsys/uco/service/CustomerProfileService.java b/src/main/java/com/mfsys/uco/service/CustomerProfileService.java index 21696b9..fa6aa4c 100644 --- a/src/main/java/com/mfsys/uco/service/CustomerProfileService.java +++ b/src/main/java/com/mfsys/uco/service/CustomerProfileService.java @@ -1,5 +1,6 @@ package com.mfsys.uco.service; +import com.mfsys.comm.exception.ApplicationException; import com.mfsys.uco.dto.UpdateProfileRequestPayload; import com.mfsys.uco.exception.BenificiaryAlreadyExistsException; import com.mfsys.uco.model.Beneficiary; @@ -9,6 +10,7 @@ import com.mfsys.uco.repository.BeneficiaryRepository; import com.mfsys.uco.repository.CustomerProfileRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; import java.util.List; import java.util.Optional; @@ -18,6 +20,7 @@ import java.util.Optional; public class CustomerProfileService { private final CustomerProfileRepository customerProfileRepository; private final BeneficiaryRepository beneficiaryRepository; + private final FileStorageService fileStorageService; public void deleteBeneficiary(String porOrgacode, String email, String mbmBkmsnumberRef) { beneficiaryRepository.deleteByMbmBkmsnumberRefAndPorOrgacodeAndEmail(mbmBkmsnumberRef, porOrgacode, email); @@ -27,12 +30,21 @@ public class CustomerProfileService { return customerProfileRepository.findbyEmail(porOrgacode, email); } - public void updateCustomerProfile(UpdateProfileRequestPayload updateProfileRequestPayload) { - customerProfileRepository.findById(new CustomerProfileId(updateProfileRequestPayload.getPorOrgacode(), updateProfileRequestPayload.getCmpCustcode())) - .ifPresent(customerProfile -> { - customerProfile.setCmpCustImage(updateProfileRequestPayload.getCmpCustImage()); - customerProfileRepository.save(customerProfile); - }); + public void updateCustomerProfile(String porOrgacode, String cmpCustcode, MultipartFile image) { + CustomerProfile customerProfile = customerProfileRepository + .findById(new CustomerProfileId(porOrgacode, cmpCustcode)) + .orElseThrow(() -> new ApplicationException( + porOrgacode, + "ERR_CUSTOMER_NOT_FOUND", + new Object[]{cmpCustcode})); + + // delete old image from disk if exists + fileStorageService.deleteImage(customerProfile.getCmpCustImage()); + + // save new image and store path + String imagePath = fileStorageService.saveImage(cmpCustcode, image); + customerProfile.setCmpCustImage(imagePath); + customerProfileRepository.save(customerProfile); } public void addBeneficiary(Beneficiary beneficiary) { diff --git a/src/main/java/com/mfsys/uco/service/FileStorageService.java b/src/main/java/com/mfsys/uco/service/FileStorageService.java new file mode 100644 index 0000000..072e16b --- /dev/null +++ b/src/main/java/com/mfsys/uco/service/FileStorageService.java @@ -0,0 +1,54 @@ +package com.mfsys.uco.service; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.UUID; + +@Service +public class FileStorageService { + + @Value("${file.upload-dir}") + private String uploadDir; + + public String saveImage(String custcode, MultipartFile file) { + try { + Path uploadPath = Paths.get(uploadDir).toAbsolutePath().normalize(); + Files.createDirectories(uploadPath); + + String extension = getExtension(file.getOriginalFilename()); + String filename = custcode + "_" + UUID.randomUUID() + "." + extension; + Path targetPath = uploadPath.resolve(filename); + + Files.copy(file.getInputStream(), targetPath, StandardCopyOption.REPLACE_EXISTING); + + return uploadDir + "/" + filename; + } catch (IOException e) { + throw new RuntimeException("Failed to store image for custcode: " + custcode, e); + } + } + + public void deleteImage(String imagePath) { + try { + if (imagePath != null) { + Path path = Paths.get(imagePath).toAbsolutePath().normalize(); + Files.deleteIfExists(path); + } + } catch (IOException e) { + // log and continue — don't fail the update if old file delete fails + } + } + + private String getExtension(String filename) { + if (filename != null && filename.contains(".")) { + return filename.substring(filename.lastIndexOf(".") + 1).toLowerCase(); + } + return "jpg"; + } +} \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index b86a227..51f5e8a 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,17 +1,17 @@ server: port: 8082 + tomcat: + max-http-form-post-size: -1 + max-swallow-size: -1 spring: application: name: UCO-SERVICE datasource: driver-class-name: com.mysql.cj.jdbc.Driver - # url: jdbc:mysql://localhost:3306/uco - # username: root - # password: root - url: jdbc:mysql://${UCO_SQL_DB_MACHINE_IP}/uco - username: ${UCO_SQL_DB_USER} - password: ${UCO_SQL_DB_PASSWORD} + url: jdbc:mysql://${UCO_SQL_DB_MACHINE_IP:localhost}/uco + username: ${UCO_SQL_DB_USER:root} + password: ${UCO_SQL_DB_PASSWORD:root} jpa: show-sql: true hibernate: @@ -19,6 +19,13 @@ spring: properties: hibernate: dialect: org.hibernate.dialect.MySQLDialect + servlet: + multipart: + max-file-size: 5MB + max-request-size: 5MB + +file: + upload-dir: uploads/profiles eureka: instance: @@ -35,4 +42,4 @@ application: secret-key: 404E635266556A586E3272357538782F413F4428472B4B6250645367566B5970 expiration: 86400000 refresh-token: - expiration: 604800000 # 7 days \ No newline at end of file + expiration: 604800000 \ No newline at end of file