diff --git a/src/main/java/com/goi/erp/config/JwtAuthenticationFilter.java b/src/main/java/com/goi/erp/config/JwtAuthenticationFilter.java index c1b7fd7..3e09a9d 100644 --- a/src/main/java/com/goi/erp/config/JwtAuthenticationFilter.java +++ b/src/main/java/com/goi/erp/config/JwtAuthenticationFilter.java @@ -55,8 +55,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { if (needsAuthentication && jwtService.isTokenValid(jwt)) { - // 토큰에서 empUuid와 PermissionSet 추출 - String empUuid = jwtService.extractEmpUuid(jwt); + // 토큰에서 loginId와 PermissionSet 추출 + String loginId = jwtService.extractLoginId(jwt); PermissionSet permissionSet = jwtService.getPermissions(jwt); if (permissionSet == null) { @@ -70,7 +70,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { // PermissionAuthenticationToken 생성 PermissionAuthenticationToken authToken = - new PermissionAuthenticationToken(empUuid, permissionSet, authorities); + new PermissionAuthenticationToken(loginId, permissionSet, authorities); // SecurityContextHolder에 세팅 SecurityContextHolder.getContext().setAuthentication(authToken); diff --git a/src/main/java/com/goi/erp/controller/CustomerController.java b/src/main/java/com/goi/erp/controller/CustomerController.java index e90d5d4..7ff39be 100644 --- a/src/main/java/com/goi/erp/controller/CustomerController.java +++ b/src/main/java/com/goi/erp/controller/CustomerController.java @@ -81,7 +81,7 @@ public class CustomerController { } // READ ONE - @GetMapping("/{uuid}") + @GetMapping("/uuid/{uuid}") public ResponseEntity getCustomer(@PathVariable UUID uuid) { // 권한 체크 PermissionAuthenticationToken auth = (PermissionAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); @@ -99,7 +99,7 @@ public class CustomerController { } // UPDATE - @PatchMapping("/{uuid}") + @PatchMapping("/uuid/{uuid}") public ResponseEntity updateCustomer( @PathVariable UUID uuid, @RequestBody CustomerRequestDto requestDto) { @@ -119,7 +119,7 @@ public class CustomerController { } // DELETE - @DeleteMapping("/{uuid}") + @DeleteMapping("/uuid/{uuid}") public ResponseEntity deleteCustomer(@PathVariable UUID uuid) { // 권한 체크 PermissionAuthenticationToken auth = (PermissionAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); @@ -138,7 +138,7 @@ public class CustomerController { } // from MIS - @GetMapping("/{cusNo}") + @GetMapping("/no/{cusNo}") public ResponseEntity getCustomer(@PathVariable String cusNo) { // 권한 체크 PermissionAuthenticationToken auth = (PermissionAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); @@ -157,7 +157,7 @@ public class CustomerController { return ResponseEntity.ok(customer); } - @PutMapping("/{cusNo}") + @PatchMapping("/no/{cusNo}") public ResponseEntity updateCustomer(@PathVariable String cusNo, @RequestBody CustomerRequestDto dto) { // 권한 체크 diff --git a/src/main/java/com/goi/erp/dto/CustomerRequestDto.java b/src/main/java/com/goi/erp/dto/CustomerRequestDto.java index 5a9f7b8..efd0e18 100644 --- a/src/main/java/com/goi/erp/dto/CustomerRequestDto.java +++ b/src/main/java/com/goi/erp/dto/CustomerRequestDto.java @@ -1,30 +1,62 @@ package com.goi.erp.dto; import lombok.Data; + import java.math.BigDecimal; import java.time.LocalDate; -import java.time.LocalTime; @Data public class CustomerRequestDto { - private String cusNo; - private String cusName; - private String cusStatus; - private Integer cusAreaId; - private String cusAddress1; - private String cusAddress2; - private String cusPostalCode; - private String cusCity; - private String cusProvince; - private BigDecimal cusGeoLat; - private BigDecimal cusGeoLon; - private String cusEmail; - private String cusPhone; - private String cusPhoneExt; - private LocalTime cusOpenTime; - private String cusNote; - private LocalDate cusContractDate; - private String cusContractedBy; - private LocalDate cusInstallDate; - private String cusInstallLocatoin; + + private String cusNo; // c_accountno + private String cusName; // c_name + private String cusStatus; // c_status → ('A', 'I', 'D' 등) + private Integer cusAreaId; // region / area mapping + private String cusAddress1; // c_address + private String cusAddress2; // c_mailingaddr or c_location + private String cusPostalCode; // c_postal + private String cusCity; // c_city + private String cusProvince; // c_province + private Double cusGeoLat; // c_geolat + private Double cusGeoLon; // c_geolon + private String cusEmail; // c_email + private String cusPhone; // c_phone + private String cusPhoneExt; // c_phoneext + + private LocalDate cusContractDate; // c_contractdate + private String cusContractedBy; // c_contractby + private LocalDate cusInstallDate; // c_installdate + + private BigDecimal cusFullCycle; // c_fullcycle + private Boolean cusFullCycleFlag; // c_fullcycleflag + private BigDecimal cusFullCycleForced; // c_fullcycleforced + private LocalDate cusFullCycleForcedDate; // c_forceddate + + private String cusSchedule; // c_schedule + private String cusScheduledays; // c_scheduleday + + private LocalDate cusLastPaidDate; // c_lastpaiddate + private Double cusRate; // c_rate + private String cusPayMethod; // c_paymenttype + private String cusAccountNo; // c_accountno + + private LocalDate cusIsccDate; // c_form_eu + private LocalDate cusCorsiaDate; // c_form_corsia + private String cusHstNo; // c_hstno + + private LocalDate cusTerminatedDate; + private String cusTerminationReason; + private String cusInstallLocation; + private LocalDate cusLastPickupDate; + private Integer cusLastPickupQty; + private Double cusLastPickupLat; + private Double cusLastPickupLon; + + private String cusOpenTime; + private String cusComment; + private Integer cusLastPickupMin; + + private String loginUser; + } + diff --git a/src/main/java/com/goi/erp/dto/CustomerResponseDto.java b/src/main/java/com/goi/erp/dto/CustomerResponseDto.java index e012581..4befac3 100644 --- a/src/main/java/com/goi/erp/dto/CustomerResponseDto.java +++ b/src/main/java/com/goi/erp/dto/CustomerResponseDto.java @@ -1,23 +1,25 @@ package com.goi.erp.dto; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; + import java.math.BigDecimal; import java.time.LocalDate; -import java.time.LocalTime; import java.util.UUID; @Data @Builder +@NoArgsConstructor +@AllArgsConstructor public class CustomerResponseDto { - private UUID cusUuid; + private UUID cusUuid; private String cusNo; private String cusName; private String cusStatus; - private Integer cusAreaId; private String cusAddress1; private String cusAddress2; - private String cusPostalCode; private String cusCity; private String cusProvince; private BigDecimal cusGeoLat; @@ -25,10 +27,30 @@ public class CustomerResponseDto { private String cusEmail; private String cusPhone; private String cusPhoneExt; - private LocalTime cusOpenTime; - private String cusNote; private LocalDate cusContractDate; private String cusContractedBy; private LocalDate cusInstallDate; - private String cusInstallLocatoin; + private String cusInstallLocation; + private LocalDate cusLastPickupDate; + private Integer cusLastPickupQty; + private BigDecimal cusLastPickupLat; + private BigDecimal cusLastPickupLon; + private BigDecimal cusFullCycle; + private Boolean cusFullCycleFlag; + private BigDecimal cusFullCycleForced; + private LocalDate cusFullCycleForcedDate; + private String cusSchedule; + private String cusScheduledays; + private LocalDate cusLastPaidDate; + private BigDecimal cusRate; + private String cusPayMethod; + private String cusAccountNo; + private LocalDate cusIsccDate; + private LocalDate cusCorsiaDate; + private String cusHstNo; + private LocalDate cusTerminatedDate; + private String cusTerminationReason; + private Integer cusLastPickupMin; + private String cusOpenTime; + private String cusComment; } diff --git a/src/main/java/com/goi/erp/entity/Customer.java b/src/main/java/com/goi/erp/entity/Customer.java index c923de9..fbf47d1 100644 --- a/src/main/java/com/goi/erp/entity/Customer.java +++ b/src/main/java/com/goi/erp/entity/Customer.java @@ -14,7 +14,6 @@ import lombok.NoArgsConstructor; import java.math.BigDecimal; import java.time.LocalDate; -import java.time.LocalTime; import java.util.UUID; @Entity @@ -56,23 +55,23 @@ public class Customer { private String cusPhone; private String cusPhoneExt; - private LocalTime cusOpenTime; - private String cusNote; + private String cusOpenTime; + private String cusComment; private LocalDate cusContractDate; private String cusContractedBy; private LocalDate cusInstallDate; - private String cusInstallLocatoin; + private String cusInstallLocation; private LocalDate cusLastPickupDate; private Integer cusLastPickupQty; private BigDecimal cusLastPickupLat; private BigDecimal cusLastPickupLon; - private Integer cusFullCycle; + private BigDecimal cusFullCycle; private Boolean cusFullCycleFlag; - private Integer cusFullCycleForced; + private BigDecimal cusFullCycleForced; private LocalDate cusFullCycleForcedDate; private String cusSchedule; @@ -90,4 +89,5 @@ public class Customer { private LocalDate cusTerminatedDate; private String cusTerminationReason; + private Integer cusLastPickupMin; } diff --git a/src/main/java/com/goi/erp/repository/CustomerRepository.java b/src/main/java/com/goi/erp/repository/CustomerRepository.java index 453a3cf..ad7594e 100644 --- a/src/main/java/com/goi/erp/repository/CustomerRepository.java +++ b/src/main/java/com/goi/erp/repository/CustomerRepository.java @@ -18,7 +18,7 @@ public interface CustomerRepository extends JpaRepository { "c.cusUuid, c.cusNo, c.cusName, c.cusStatus, c.cusAreaId, " + "c.cusAddress1, c.cusAddress2, c.cusPostalCode, c.cusCity, c.cusProvince, " + "c.cusGeoLat, c.cusGeoLon, c.cusEmail, c.cusPhone, c.cusPhoneExt, " + - "c.cusOpenTime, c.cusNote, c.cusContractDate, c.cusContractedBy, c.cusInstallDate, c.cusInstallLocatoin) " + + "c.cusOpenTime, c.cusComment, c.cusContractDate, c.cusContractedBy, c.cusInstallDate, c.cusInstallLocation) " + "FROM Customer c WHERE c.cusUuid = :uuid") Optional findCustomerDtoByCusUuid(UUID uuid); @@ -26,7 +26,7 @@ public interface CustomerRepository extends JpaRepository { "c.cusUuid, c.cusNo, c.cusName, c.cusStatus, c.cusAreaId, " + "c.cusAddress1, c.cusAddress2, c.cusPostalCode, c.cusCity, c.cusProvince, " + "c.cusGeoLat, c.cusGeoLon, c.cusEmail, c.cusPhone, c.cusPhoneExt, " + - "c.cusOpenTime, c.cusNote, c.cusContractDate, c.cusContractedBy, c.cusInstallDate, c.cusInstallLocatoin) " + + "c.cusOpenTime, c.cusComment, c.cusContractDate, c.cusContractedBy, c.cusInstallDate, c.cusInstallLocation) " + "FROM Customer c") Page findAllCustomerDtos(Pageable pageable); @@ -34,5 +34,6 @@ public interface CustomerRepository extends JpaRepository { // from MIS Optional findByCusNo(String cusNo); + boolean existsByCusNo(String cusNo); } diff --git a/src/main/java/com/goi/erp/service/CustomerService.java b/src/main/java/com/goi/erp/service/CustomerService.java index 844f1da..5dca64f 100644 --- a/src/main/java/com/goi/erp/service/CustomerService.java +++ b/src/main/java/com/goi/erp/service/CustomerService.java @@ -3,14 +3,26 @@ package com.goi.erp.service; import com.goi.erp.dto.CustomerRequestDto; import com.goi.erp.dto.CustomerResponseDto; import com.goi.erp.entity.Customer; +import com.goi.erp.entity.EntityChangeLog; import com.goi.erp.repository.CustomerRepository; +import com.goi.erp.repository.EntityChangeLogRepository; + +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; +import org.springframework.beans.BeanUtils; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Map; +import java.util.Objects; import java.util.UUID; @Service @@ -18,18 +30,53 @@ import java.util.UUID; public class CustomerService { private final CustomerRepository customerRepository; + private final EntityChangeLogRepository entityChangeLogRepository; public CustomerResponseDto createCustomer(CustomerRequestDto dto) { - Customer customer = Customer.builder() + Customer customer = Customer.builder() .cusUuid(UUID.randomUUID()) - .cusName(dto.getCusName()) .cusNo(dto.getCusNo()) + .cusName(dto.getCusName()) .cusStatus(dto.getCusStatus()) + + .cusAreaId(dto.getCusAreaId()) .cusAddress1(dto.getCusAddress1()) .cusAddress2(dto.getCusAddress2()) + .cusPostalCode(dto.getCusPostalCode()) .cusCity(dto.getCusCity()) .cusProvince(dto.getCusProvince()) + .cusGeoLat(dto.getCusGeoLat() != null ? BigDecimal.valueOf(dto.getCusGeoLat()) : null) + .cusGeoLon(dto.getCusGeoLon() != null ? BigDecimal.valueOf(dto.getCusGeoLon()) : null) + .cusEmail(dto.getCusEmail()) + .cusPhone(dto.getCusPhone()) + .cusPhoneExt(dto.getCusPhoneExt()) + + .cusContractDate(dto.getCusContractDate()) + .cusContractedBy(dto.getCusContractedBy()) + .cusInstallDate(dto.getCusInstallDate()) + + .cusFullCycle(dto.getCusFullCycle()) + .cusFullCycleFlag(dto.getCusFullCycleFlag()) + .cusFullCycleForced(dto.getCusFullCycleForced()) + .cusFullCycleForcedDate(dto.getCusFullCycleForcedDate()) + + .cusSchedule(dto.getCusSchedule()) + .cusScheduledays(dto.getCusScheduledays()) + + .cusLastPaidDate(dto.getCusLastPaidDate()) + .cusRate(dto.getCusRate() != null ? BigDecimal.valueOf(dto.getCusRate()) : null) + .cusPayMethod(dto.getCusPayMethod()) + .cusAccountNo(dto.getCusAccountNo()) + + .cusIsccDate(dto.getCusIsccDate()) + .cusCorsiaDate(dto.getCusCorsiaDate()) + .cusHstNo(dto.getCusHstNo()) + + .cusOpenTime(dto.getCusOpenTime()) + .cusComment(dto.getCusComment()) + .cusInstallLocation(dto.getCusInstallLocation()) .build(); + customer = customerRepository.save(customer); return mapToDto(customer); // 생성 시에는 여전히 엔티티 → DTO 필요 } @@ -47,16 +94,7 @@ public class CustomerService { public CustomerResponseDto updateCustomer(UUID uuid, CustomerRequestDto dto) { Customer customer = customerRepository.findByCusUuid(uuid) .orElseThrow(() -> new RuntimeException("Customer not found")); - - if (dto.getCusName() != null) customer.setCusName(dto.getCusName()); - if (dto.getCusStatus() != null) customer.setCusStatus(dto.getCusStatus()); - if (dto.getCusAddress1() != null) customer.setCusAddress1(dto.getCusAddress1()); - if (dto.getCusAddress2() != null) customer.setCusAddress2(dto.getCusAddress2()); - if (dto.getCusCity() != null) customer.setCusCity(dto.getCusCity()); - if (dto.getCusProvince() != null) customer.setCusProvince(dto.getCusProvince()); - - customerRepository.save(customer); - return mapToDto(customer); + return updateCustomerInternal(customer, dto); } public void deleteCustomer(UUID uuid) { @@ -64,15 +102,101 @@ public class CustomerService { .orElseThrow(() -> new RuntimeException("Customer not found")); customerRepository.delete(customer); } + + private CustomerResponseDto updateCustomerInternal(Customer customer, CustomerRequestDto dto) { - private CustomerResponseDto mapToDto(Customer customer) { - return CustomerResponseDto.builder() - .cusUuid(customer.getCusUuid()) - .cusName(customer.getCusName()) - .cusNo(customer.getCusNo()) - .cusStatus(customer.getCusStatus()) - .build(); + if (dto.getCusName() != null) customer.setCusName(dto.getCusName()); + if (dto.getCusStatus() != null) customer.setCusStatus(dto.getCusStatus()); + if (dto.getCusNo() != null) customer.setCusNo(dto.getCusNo()); + if (dto.getCusAreaId() != null) customer.setCusAreaId(dto.getCusAreaId()); + if (dto.getCusAddress1() != null) customer.setCusAddress1(dto.getCusAddress1()); + if (dto.getCusAddress2() != null) customer.setCusAddress2(dto.getCusAddress2()); + if (dto.getCusPostalCode() != null) customer.setCusPostalCode(dto.getCusPostalCode()); + if (dto.getCusCity() != null) customer.setCusCity(dto.getCusCity()); + if (dto.getCusProvince() != null) customer.setCusProvince(dto.getCusProvince()); + customer.setCusGeoLat(dto.getCusGeoLat() != null ? BigDecimal.valueOf(dto.getCusGeoLat()) : null); + customer.setCusGeoLon(dto.getCusGeoLon() != null ? BigDecimal.valueOf(dto.getCusGeoLon()) : null); + if (dto.getCusEmail() != null) customer.setCusEmail(dto.getCusEmail()); + if (dto.getCusPhone() != null) customer.setCusPhone(dto.getCusPhone()); + if (dto.getCusPhoneExt() != null) customer.setCusPhoneExt(dto.getCusPhoneExt()); + if (dto.getCusContractDate() != null) customer.setCusContractDate(dto.getCusContractDate()); + if (dto.getCusContractedBy() != null) customer.setCusContractedBy(dto.getCusContractedBy()); + if (dto.getCusInstallDate() != null) customer.setCusInstallDate(dto.getCusInstallDate()); + if (dto.getCusFullCycle() != null) customer.setCusFullCycle(dto.getCusFullCycle()); + if (dto.getCusFullCycleFlag() != null) customer.setCusFullCycleFlag(dto.getCusFullCycleFlag()); + if (dto.getCusFullCycleForced() != null) customer.setCusFullCycleForced(dto.getCusFullCycleForced()); + if (dto.getCusFullCycleForcedDate() != null) customer.setCusFullCycleForcedDate(dto.getCusFullCycleForcedDate()); + if (dto.getCusSchedule() != null) customer.setCusSchedule(dto.getCusSchedule()); + if (dto.getCusScheduledays() != null) customer.setCusScheduledays(dto.getCusScheduledays()); + if (dto.getCusLastPaidDate() != null) customer.setCusLastPaidDate(dto.getCusLastPaidDate()); + customer.setCusRate(dto.getCusRate() != null ? BigDecimal.valueOf(dto.getCusRate()) : null); + if (dto.getCusPayMethod() != null) customer.setCusPayMethod(dto.getCusPayMethod()); + if (dto.getCusIsccDate() != null) customer.setCusIsccDate(dto.getCusIsccDate()); + if (dto.getCusCorsiaDate() != null) customer.setCusCorsiaDate(dto.getCusCorsiaDate()); + if (dto.getCusHstNo() != null) customer.setCusHstNo(dto.getCusHstNo()); + if (dto.getCusTerminatedDate() != null) customer.setCusTerminatedDate(dto.getCusTerminatedDate()); + if (dto.getCusTerminationReason() != null) customer.setCusTerminationReason(dto.getCusTerminationReason()); + if (dto.getCusLastPickupDate() != null) customer.setCusLastPickupDate(dto.getCusLastPickupDate()); + if (dto.getCusLastPickupQty() != null) customer.setCusLastPickupQty(dto.getCusLastPickupQty()); + customer.setCusLastPickupLat(dto.getCusLastPickupLat() != null ? BigDecimal.valueOf(dto.getCusLastPickupLat()) : null); + customer.setCusLastPickupLon(dto.getCusLastPickupLon() != null ? BigDecimal.valueOf(dto.getCusLastPickupLon()) : null); + if (dto.getCusOpenTime() != null) customer.setCusOpenTime(dto.getCusOpenTime()); + if (dto.getCusComment() != null) customer.setCusComment(dto.getCusComment()); + if (dto.getCusInstallLocation() != null) customer.setCusInstallLocation(dto.getCusInstallLocation()); + + customerRepository.save(customer); + return mapToDto(customer); } + + + public CustomerResponseDto mapToDto(Customer customer) { + if (customer == null) return null; + + CustomerResponseDto dto = new CustomerResponseDto(); + dto.setCusUuid(customer.getCusUuid()); + dto.setCusNo(customer.getCusNo()); + dto.setCusName(customer.getCusName()); + dto.setCusStatus(customer.getCusStatus()); + dto.setCusAddress1(customer.getCusAddress1()); + dto.setCusAddress2(customer.getCusAddress2()); + dto.setCusCity(customer.getCusCity()); + dto.setCusProvince(customer.getCusProvince()); + dto.setCusGeoLat(customer.getCusGeoLat()); + dto.setCusGeoLon(customer.getCusGeoLon()); + dto.setCusEmail(customer.getCusEmail()); + dto.setCusPhone(customer.getCusPhone()); + dto.setCusPhoneExt(customer.getCusPhoneExt()); + dto.setCusContractDate(customer.getCusContractDate()); + dto.setCusContractedBy(customer.getCusContractedBy()); + dto.setCusInstallDate(customer.getCusInstallDate()); + dto.setCusInstallLocation(customer.getCusInstallLocation()); + dto.setCusLastPickupDate(customer.getCusLastPickupDate()); + dto.setCusLastPickupQty(customer.getCusLastPickupQty()); + dto.setCusLastPickupLat(customer.getCusLastPickupLat()); + dto.setCusLastPickupLon(customer.getCusLastPickupLon()); + dto.setCusFullCycle(customer.getCusFullCycle()); + dto.setCusFullCycleFlag(customer.getCusFullCycleFlag()); + dto.setCusFullCycleForced(customer.getCusFullCycleForced()); + dto.setCusFullCycleForcedDate(customer.getCusFullCycleForcedDate()); + dto.setCusSchedule(customer.getCusSchedule()); + dto.setCusScheduledays(customer.getCusScheduledays()); + dto.setCusLastPaidDate(customer.getCusLastPaidDate()); + dto.setCusRate(customer.getCusRate()); + dto.setCusPayMethod(customer.getCusPayMethod()); + dto.setCusAccountNo(customer.getCusAccountNo()); + dto.setCusIsccDate(customer.getCusIsccDate()); + dto.setCusCorsiaDate(customer.getCusCorsiaDate()); + dto.setCusHstNo(customer.getCusHstNo()); + dto.setCusTerminatedDate(customer.getCusTerminatedDate()); + dto.setCusTerminationReason(customer.getCusTerminationReason()); + dto.setCusLastPickupMin(customer.getCusLastPickupMin()); + dto.setCusOpenTime(customer.getCusOpenTime()); + dto.setCusComment(customer.getCusComment()); + dto.setCusInstallLocation(customer.getCusInstallLocation()); + + return dto; + } + // from MIS public CustomerResponseDto getCustomerByNo(String cusNo) { @@ -80,19 +204,108 @@ public class CustomerService { .orElseThrow(() -> new RuntimeException("Customer not found")); return mapToDto(customer); } + + @Transactional + public CustomerResponseDto updateCustomerByNo(String cusNo, CustomerRequestDto newCustomer) { - public CustomerResponseDto updateCustomerByNo(String cusNo, CustomerRequestDto dto) { - Customer customer = customerRepository.findByCusNo(cusNo) + Customer oldCustomer = customerRepository.findByCusNo(cusNo) .orElseThrow(() -> new RuntimeException("Customer not found")); - customer.setCusName(dto.getCusName()); - customer.setCusStatus(dto.getCusStatus()); - customer.setCusAddress1(dto.getCusAddress1()); - customer.setCusAddress2(dto.getCusAddress2()); - customer.setCusCity(dto.getCusCity()); - customer.setCusProvince(dto.getCusProvince()); + // 1. OLD VALUE 백업 (deep copy) + Customer beforeUpdate = new Customer(); + BeanUtils.copyProperties(oldCustomer, beforeUpdate); + + // 2. 주소/우편번호 변경 시 geo 초기화 + if ((newCustomer.getCusAddress1() != null && !newCustomer.getCusAddress1().equals(oldCustomer.getCusAddress1())) || + (newCustomer.getCusPostalCode() != null && !newCustomer.getCusPostalCode().equals(oldCustomer.getCusPostalCode()))) { + oldCustomer.setCusGeoLat(null); + oldCustomer.setCusGeoLon(null); + } - customerRepository.save(customer); - return mapToDto(customer); + // 3. 실제 업데이트 적용 + CustomerResponseDto response = updateCustomerInternal(oldCustomer, newCustomer); + + // 4. 변경 비교 (old vs new) + String misLoginUser = newCustomer.getLoginUser(); // todo: 내부 loginId 로 변경 + String loginId = SecurityContextHolder.getContext().getAuthentication().getName(); // 현재는 MIS login user + compareAndLogChanges(beforeUpdate, oldCustomer, misLoginUser, loginId); + + return response; } + + + // set change log + private void compareAndLogChanges(Customer oldData, Customer newData, String changedBy, String createdBy) { + + // 필드 → DB 컬럼 매핑 + Map fieldToColumn = Map.ofEntries( + Map.entry("cusName", "cus_name"), + Map.entry("cusEmail", "cus_email"), + Map.entry("cusPhone", "cus_phone"), + Map.entry("cusGeoLat", "cus_geo_lat"), + Map.entry("cusGeoLon", "cus_geo_lon"), + Map.entry("cusStatus", "cus_status"), + Map.entry("cusAddress1", "cus_address1"), + Map.entry("cusAddress2", "cus_address2"), + Map.entry("cusPostalCode", "cus_postal_code"), + Map.entry("cusCity", "cus_city"), + Map.entry("cusProvince", "cus_province"), + Map.entry("cusPhoneExt", "cus_phone_ext"), + Map.entry("cusContractDate", "cus_contract_date"), + Map.entry("cusContractedBy", "cus_contracted_by"), + Map.entry("cusInstallDate", "cus_install_date"), + Map.entry("cusFullCycle", "cus_full_cycle"), + Map.entry("cusFullCycleFlag", "cus_full_cycle_flag"), + Map.entry("cusFullCycleForced", "cus_full_cycle_forced"), + Map.entry("cusFullCycleForcedDate", "cus_full_cycle_forced_date"), + Map.entry("cusSchedule", "cus_schedule"), + Map.entry("cusScheduledays", "cus_scheduledays"), + Map.entry("cusLastPaidDate", "cus_last_paid_date"), + Map.entry("cusRate", "cus_rate"), + Map.entry("cusPayMethod", "cus_pay_method"), + Map.entry("cusAccountNo", "cus_account_no"), + Map.entry("cusIsccDate", "cus_iscc_date"), + Map.entry("cusCorsiaDate", "cus_corsia_date"), + Map.entry("cusHstNo", "cus_hst_no"), + Map.entry("cusOpenTime", "cus_open_time"), + Map.entry("cusComment", "cus_comment"), + Map.entry("cusInstallLocation", "cus_install_location") + ); + + Class clazz = Customer.class; + + for (var entry : fieldToColumn.entrySet()) { + String fieldName = entry.getKey(); + String columnName = entry.getValue(); + + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + + Object oldVal = field.get(oldData); + Object newVal = field.get(newData); + + if (!Objects.equals(oldVal, newVal)) { + entityChangeLogRepository.save( + EntityChangeLog.builder() + .eclEntityType("Customer") + .eclEntityId(newData.getCusId()) + .eclFieldName(fieldName) + .eclColumnName(columnName) + .eclOldValue(oldVal == null ? null : oldVal.toString()) + .eclNewValue(newVal == null ? null : newVal.toString()) + .eclEffectiveDate(LocalDate.now()) + .eclChangedBy(changedBy) + .eclChangedAt(LocalDateTime.now()) + .eclCreatedBy(changedBy) + .build() + ); + } + + } catch (Exception e) { + throw new RuntimeException("Failed to compare field: " + fieldName, e); + } + } + } + } diff --git a/src/main/java/com/goi/erp/token/JwtService.java b/src/main/java/com/goi/erp/token/JwtService.java index 94894d6..37e9026 100644 --- a/src/main/java/com/goi/erp/token/JwtService.java +++ b/src/main/java/com/goi/erp/token/JwtService.java @@ -34,6 +34,13 @@ public class JwtService { public String extractEmpUuid(String token) { return extractClaim(token, Claims::getSubject); } + + /** + * loginId 추출 + */ + public String extractLoginId(String token) { + return extractClaim(token, claims -> claims.get("loginId", String.class)); + } /** * firstName 추출 @@ -117,7 +124,7 @@ public class JwtService { JwtService jwtService = new JwtService(); jwtService.secretKey = "D0HaHnTPKLkUO9ULL1Ulm6XDZjhzuFtvTCcxTxSoCS8="; - String token = "eyJhbGciOiJIUzI1NiJ9.eyJmaXJzdE5hbWUiOiJIeW9qaW4iLCJsYXN0TmFtZSI6IkFobiIsInBlcm1pc3Npb25zIjpbIkFMTCJdLCJyb2xlcyI6WyJBZG1pbiJdLCJzdWIiOiJhMjM4ZWQ0OC03OGRjLTQ2YWEtOWNiMC1hNWYxZGQyZDJmMTMiLCJpYXQiOjE3NjM2NDYzNzQsImV4cCI6MTc2MzczMjc3NH0.HwFZeNbxVldcBeiqc3TUO3x5on2Quy7_Yd_HTkIfOR4"; + String token = "eyJhbGciOiJIUzI1NiJ9.eyJmaXJzdE5hbWUiOiJNSVMiLCJsYXN0TmFtZSI6IkNTIiwibG9naW5JZCI6ImNzX21pcyIsInBlcm1pc3Npb25zIjpbIkg6UjpTIiwiQzpDOkEiLCJDOlI6QSIsIkM6VTpBIiwiQzpEOkEiXSwicm9sZXMiOlsiQ1MgU3RhZmYiXSwic3ViIjoiMWU3NTU4YzYtOTFhZC00ZDcxLTg3ZTUtZGJjZmZiYjk5Zjg1IiwiaWF0IjoxNzY0MzQ3Nzg1LCJleHAiOjIwNzk3MDc3ODV9.lL-ZHEpiribxIrNmeYp6LAeU11z-KuRbgELkWjHCCSc"; // user 정보 Claims claims = jwtService.extractAllClaims(token);