[customer-daily-order]

- Added
[all]
- Changed ID data type to Long
- Added Created By, Updated By
This commit is contained in:
Hyojin Ahn 2025-12-02 11:05:49 -05:00
parent c8854d8a13
commit 06d24c2e6f
14 changed files with 734 additions and 26 deletions

View File

@ -14,7 +14,7 @@ public class ApplicationConfig {
private String jwtSecret;
@Bean
public AuditorAware<Integer> auditorAware() {
public AuditorAware<String> auditorAware() {
return new ApplicationAuditAware(jwtSecret);
}

View File

@ -2,8 +2,10 @@ package com.goi.erp.controller;
import com.goi.erp.common.permission.PermissionChecker;
import com.goi.erp.common.permission.PermissionSet;
import com.goi.erp.dto.CustomerDailyOrderResponseDto;
import com.goi.erp.dto.CustomerRequestDto;
import com.goi.erp.dto.CustomerResponseDto;
import com.goi.erp.service.CustomerDailyOrderService;
import com.goi.erp.service.CustomerService;
import com.goi.erp.token.PermissionAuthenticationToken;
@ -11,12 +13,14 @@ import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.util.UUID;
@RestController
@ -33,6 +37,7 @@ public class CustomerController {
private int maxSize;
private final CustomerService customerService;
private final CustomerDailyOrderService dailyOrderService;
// CREATE
@PostMapping
@ -176,4 +181,28 @@ public class CustomerController {
CustomerResponseDto updated = customerService.updateCustomerByNo(cusNo, dto);
return ResponseEntity.ok(updated);
}
// READ DAILY ORDER BY CUSTOMER NO + DATE
@GetMapping("/no/{cusNo}/daily-orders/{orderDate}")
public ResponseEntity<CustomerDailyOrderResponseDto> getDailyOrderByCustomerNo(
@PathVariable String cusNo,
@PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate orderDate
) {
PermissionAuthenticationToken auth =
(PermissionAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
if (auth == null || auth.getPermissionSet() == null) {
throw new AccessDeniedException("Permission information is missing");
}
PermissionSet permissionSet = auth.getPermissionSet();
if (!PermissionChecker.canReadCRM(permissionSet)) {
throw new AccessDeniedException("You do not have permission to read daily order");
}
return ResponseEntity.ok(
dailyOrderService.getDailyOrderByCustomerNo(cusNo, orderDate)
);
}
}

View File

@ -0,0 +1,165 @@
package com.goi.erp.controller;
import com.goi.erp.common.permission.PermissionChecker;
import com.goi.erp.common.permission.PermissionSet;
import com.goi.erp.dto.CustomerDailyOrderRequestDto;
import com.goi.erp.dto.CustomerDailyOrderResponseDto;
import com.goi.erp.service.CustomerDailyOrderService;
import com.goi.erp.token.PermissionAuthenticationToken;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.util.UUID;
@RestController
@RequestMapping("/customer-daily-order")
@RequiredArgsConstructor
public class CustomerDailyOrderController {
@Value("${pagination.default-page:0}")
private int defaultPage;
@Value("${pagination.default-size:20}")
private int defaultSize;
@Value("${pagination.max-size:100}")
private int maxSize;
private final CustomerDailyOrderService dailyOrderService;
private PermissionSet getPermission() {
PermissionAuthenticationToken auth =
(PermissionAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
if (auth == null || auth.getPermissionSet() == null) {
throw new AccessDeniedException("Permission information is missing");
}
return auth.getPermissionSet();
}
// CREATE
@PostMapping
public ResponseEntity<CustomerDailyOrderResponseDto> createDailyOrder(
@RequestBody CustomerDailyOrderRequestDto dto) {
PermissionSet permissions = getPermission();
if (!PermissionChecker.canCreateCRM(permissions)) {
throw new AccessDeniedException("You do not have permission to create daily orders");
}
CustomerDailyOrderResponseDto created = dailyOrderService.createDailyOrder(dto);
return new ResponseEntity<>(created, HttpStatus.CREATED);
}
// READ ALL (paged)
@GetMapping
public ResponseEntity<Page<CustomerDailyOrderResponseDto>> getAllDailyOrders(
@RequestParam(required = false) Integer page,
@RequestParam(required = false) Integer size) {
PermissionSet permissions = getPermission();
if (!PermissionChecker.canReadCRMAll(permissions)) {
throw new AccessDeniedException("You do not have permission to read all daily orders");
}
int p = (page == null) ? defaultPage : page;
int s = (size == null) ? defaultSize : size;
if (s > maxSize) s = maxSize;
return ResponseEntity.ok(dailyOrderService.getAllDailyOrders(p, s));
}
// READ ONE BY UUID
@GetMapping("/{uuid}")
public ResponseEntity<CustomerDailyOrderResponseDto> getDailyOrder(@PathVariable UUID uuid) {
PermissionSet permissions = getPermission();
if (!PermissionChecker.canReadCRM(permissions)) {
throw new AccessDeniedException("You do not have permission to read daily order");
}
return ResponseEntity.ok(dailyOrderService.getDailyOrderByUuid(uuid));
}
// READ BY CUSTOMER + DATE
@GetMapping("/customer/{customerNo}/{orderDate}")
public ResponseEntity<CustomerDailyOrderResponseDto> getDailyOrderByCustomerNo(
@PathVariable String customerNo,
@PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate orderDate
)
{
PermissionSet permissions = getPermission();
if (!PermissionChecker.canReadCRM(permissions)) {
throw new AccessDeniedException("You do not have permission to read daily order");
}
return ResponseEntity.ok(dailyOrderService.getDailyOrderByCustomerNo(customerNo, orderDate));
}
// UPDATE BY CUSTOMER + DATE
@PatchMapping("/customer/{customerNo}/{orderDate}")
public ResponseEntity<CustomerDailyOrderResponseDto> updateDailyOrderByCustomerNo(
@PathVariable String customerNo,
@PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate orderDate,
@RequestBody CustomerDailyOrderRequestDto dto
) {
PermissionSet permissions = getPermission();
if (!PermissionChecker.canUpdateCRM(permissions)) {
throw new AccessDeniedException("You do not have permission to update daily order");
}
return ResponseEntity.ok(
dailyOrderService.updateDailyOrderByCustomerNoAndOrderDate(customerNo, orderDate, dto)
);
}
// UPDATE
@PatchMapping("/{uuid}")
public ResponseEntity<CustomerDailyOrderResponseDto> updateDailyOrder(
@PathVariable UUID uuid,
@RequestBody CustomerDailyOrderRequestDto dto) {
PermissionSet permissions = getPermission();
if (!PermissionChecker.canUpdateCRM(permissions)) {
throw new AccessDeniedException("You do not have permission to update daily order");
}
return ResponseEntity.ok(dailyOrderService.updateDailyOrder(uuid, dto));
}
// DELETE
@DeleteMapping("/{uuid}")
public ResponseEntity<Void> deleteDailyOrder(@PathVariable UUID uuid) {
PermissionSet permissions = getPermission();
if (!PermissionChecker.canDeleteCRM(permissions)) {
throw new AccessDeniedException("You do not have permission to delete daily order");
}
dailyOrderService.deleteDailyOrder(uuid);
return ResponseEntity.noContent().build();
}
}

View File

@ -0,0 +1,54 @@
package com.goi.erp.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;
@Data
@NoArgsConstructor
public class CustomerDailyOrderRequestDto {
private LocalDate cdoOrderDate; // 주문 날짜 (YYYY-MM-DD)
private String cdoOrderType; // 주문 타입 ('N' )
private String cdoRequestNote; // 주문 요청 메모
private Long cdoDriverId; // MIS 에서는 driverId 호출해서 employee_external_map 참조해야함
private UUID cdoDriverUuid; // ERP 에서는 uuid 호출
private Long cdoCustomerId; // 고객 ID
private String cdoCustomerNo;
private String cdoPaymentType; // 결제 타입
private String cdoCycle; // Cycle (방문 주기)
private BigDecimal cdoRate; // 요율 (리터당 가격 )
private String cdoCreatedBy; // 생성자 ID
private String cdoUpdatedBy; // 수정자 ID
private String cdoStatus; // 상태 ('A', 'F', 'D')
private String cdoVisitFlag; // 방문 여부 Flag
private LocalDateTime cdoInputAt; // 입력 시간
private BigDecimal cdoEstimatedQty; // 예상 수거량
private BigDecimal cdoQuantity; // 실제 수거량
private Integer cdoSludge; // Sludge 여부/수치
private String cdoPayStatus; // 결제 여부 ('N', 'Y')
private BigDecimal cdoPayAmount; // 결제 금액
private String cdoPayeeName; // Payee 이름
private String cdoPayeeSign; // Payee 사인 (이미지 경로 )
private BigDecimal cdoPickupLat; // 픽업 위도
private BigDecimal cdoPickupLon; // 픽업 경도
private Integer cdoPickupMin; // 픽업 작업 시간()
private String cdoLoginUser; // 로그인한 User (CreatedBy/UpdatedBy )
}

View File

@ -0,0 +1,59 @@
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.LocalDateTime;
import java.util.UUID;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CustomerDailyOrderResponseDto {
private UUID cdoUuid; // UUID
private LocalDate cdoOrderDate; // YYYYMMDD
private String cdoOrderType; // 주문 타입
private String cdoRequestNote; // 요청 메모
private Long cdoDriverId; // Driver ID
private String cdoCustomerNo; // Customer No
private String cdoPaymentType; // 결제 방식
private String cdoCycle; // Cycle
private BigDecimal cdoRate; // 요율
private LocalDateTime cdoCreatedAt; // 생성 시간
private String cdoCreatedBy; // 생성자
private LocalDateTime cdoUpdatedAt; // 수정 시간
private String cdoUpdatedBy; // 수정자
private String cdoStatus; // 상태
private String cdoVisitFlag; // 방문 여부
private LocalDateTime cdoInputAt; // 입력 시간
private BigDecimal cdoEstimatedQty; // 예상 수거량
private BigDecimal cdoQuantity; // 실제 수거량
private Integer cdoSludge; // Sludge
private String cdoPayStatus; // 결제 상태
private BigDecimal cdoPayAmount; // 결제 금액
private String cdoPayeeName; // Payee 이름
private String cdoPayeeSign; // Payee 사인
private BigDecimal cdoPickupLat; // 픽업 위도
private BigDecimal cdoPickupLon; // 픽업 경도
private Integer cdoPickupMin; // 픽업 시간()
}

View File

@ -13,7 +13,7 @@ public class CustomerRequestDto {
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 Long cusAreaId; // region / area mapping
private String cusAddress1; // c_address
private String cusAddress2; // c_mailingaddr or c_location
private String cusPostalCode; // c_postal

View File

@ -2,6 +2,7 @@ package com.goi.erp.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@ -16,17 +17,22 @@ import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.UUID;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@Entity
@Table(name = "customer")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EntityListeners(AuditingEntityListener.class)
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer cusId;
private Long cusId;
@Column(nullable = false, unique = true)
private UUID cusUuid;
@ -40,7 +46,7 @@ public class Customer {
@Column(length = 1)
private String cusStatus;
private Integer cusAreaId;
private Long cusAreaId;
private String cusAddress1;
private String cusAddress2;
@ -90,4 +96,10 @@ public class Customer {
private LocalDate cusTerminatedDate;
private String cusTerminationReason;
private Integer cusLastPickupMin;
@CreatedBy
private String cusCreatedBy;
@LastModifiedBy
private String cusUpdatedBy;
}

View File

@ -0,0 +1,105 @@
package com.goi.erp.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "customer_daily_order")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EntityListeners(AuditingEntityListener.class)
public class CustomerDailyOrder {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long cdoId;
private UUID cdoUuid;
private LocalDate cdoOrderDate;
@Column(length = 1)
private String cdoOrderType;
private String cdoRequestNote;
private Long cdoDriverId;
private Long cdoCustomerId;
private String cdoCustomerNo;
@Column(length = 10)
private String cdoPaymentType;
@Column(length = 1)
private String cdoCycle;
private BigDecimal cdoRate;
private LocalDateTime cdoCreatedAt;
@CreatedBy
@Column(name = "cdo_created_by")
private String cdoCreatedBy;
private LocalDateTime cdoUpdatedAt;
@LastModifiedBy
@Column(name = "cdo_updated_by")
private String cdoUpdatedBy;
@Column(length = 1)
private String cdoStatus;
@Column(length = 1)
private String cdoVisitFlag;
private LocalDateTime cdoInputAt;
private BigDecimal cdoEstimatedQty;
private BigDecimal cdoQuantity;
private Integer cdoSludge;
@Column(length = 1)
private String cdoPayStatus;
private BigDecimal cdoPayAmount;
@Column(length = 200)
private String cdoPayeeName;
@Column(length = 200)
private String cdoPayeeSign;
@Column(precision = 10, scale = 7)
private BigDecimal cdoPickupLat;
@Column(precision = 10, scale = 7)
private BigDecimal cdoPickupLon;
private Integer cdoPickupMin;
}

View File

@ -23,7 +23,7 @@ public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "emp_id")
private Integer empId; // 내부 PK, 외부 노출 X
private Long empId; // 내부 PK, 외부 노출 X
@Column(name = "emp_uuid", unique = true, nullable = false)
private UUID empUuid; // 외부 키로 사용

View File

@ -10,6 +10,9 @@ import jakarta.persistence.Table;
import java.time.LocalDate;
import java.time.LocalDateTime;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.LastModifiedBy;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -25,13 +28,13 @@ public class EntityChangeLog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ecl_id")
private Integer eclId;
private Long eclId;
@Column(name = "ecl_entity_type")
private String eclEntityType;
@Column(name = "ecl_entity_id")
private Integer eclEntityId;
private Long eclEntityId;
@Column(name = "ecl_field_name")
private String eclFieldName;
@ -48,12 +51,14 @@ public class EntityChangeLog {
@Column(name = "ecl_effective_date")
private LocalDate eclEffectiveDate;
@LastModifiedBy
@Column(name = "ecl_changed_by")
private String eclChangedBy;
@Column(name = "ecl_changed_at")
private LocalDateTime eclChangedAt;
@CreatedBy
@Column(name = "ecl_created_by")
private String eclCreatedBy;
}

View File

@ -0,0 +1,35 @@
package com.goi.erp.repository;
import com.goi.erp.entity.CustomerDailyOrder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
import java.util.UUID;
import java.time.LocalDate;
import java.util.List;
@Repository
public interface CustomerDailyOrderRepository extends JpaRepository<CustomerDailyOrder, Integer> {
// 기본 페이징 조회
Page<CustomerDailyOrder> findAll(Pageable pageable);
// UUID 조회
Optional<CustomerDailyOrder> findByCdoUuid(UUID cdoUuid);
// 특정 고객의 특정 날짜 주문 조회
Optional<CustomerDailyOrder> findByCdoCustomerNoAndCdoOrderDate(String cdoCustomerNo, LocalDate cdoOrderDate);
// 특정 고객의 모든 주문 리스트
List<CustomerDailyOrder> findByCdoCustomerNo(String cdoCustomerNo);
// 특정 날짜의 전체 주문
List<CustomerDailyOrder> findByCdoOrderDate(LocalDate cdoOrderDate);
// 존재 여부 체크 (중복 입력 방지)
boolean existsByCdoCustomerNoAndCdoOrderDate(String cdoCustomerNo, LocalDate cdoOrderDate);
}

View File

@ -0,0 +1,242 @@
package com.goi.erp.service;
import com.goi.erp.dto.CustomerDailyOrderRequestDto;
import com.goi.erp.dto.CustomerDailyOrderResponseDto;
import com.goi.erp.entity.CustomerDailyOrder;
import com.goi.erp.repository.CustomerDailyOrderRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;
@Service
@RequiredArgsConstructor
public class CustomerDailyOrderService {
private final CustomerDailyOrderRepository dailyOrderRepository;
/**
* CREATE
*/
public CustomerDailyOrderResponseDto createDailyOrder(CustomerDailyOrderRequestDto dto) {
CustomerDailyOrder order = CustomerDailyOrder.builder()
.cdoUuid(UUID.randomUUID())
.cdoOrderDate(dto.getCdoOrderDate())
.cdoOrderType(dto.getCdoOrderType())
.cdoRequestNote(dto.getCdoRequestNote())
.cdoDriverId(dto.getCdoDriverId())
.cdoCustomerNo(dto.getCdoCustomerNo())
.cdoPaymentType(dto.getCdoPaymentType())
.cdoCycle(dto.getCdoCycle())
.cdoRate(dto.getCdoRate())
.cdoCreatedAt(LocalDateTime.now())
.cdoCreatedBy(dto.getCdoLoginUser())
.cdoStatus(dto.getCdoStatus())
.cdoVisitFlag(dto.getCdoVisitFlag())
.cdoInputAt(dto.getCdoInputAt())
.cdoEstimatedQty(dto.getCdoEstimatedQty())
.cdoQuantity(dto.getCdoQuantity())
.cdoSludge(dto.getCdoSludge())
.cdoPayStatus(dto.getCdoPayStatus())
.cdoPayAmount(dto.getCdoPayAmount())
.cdoPayeeName(dto.getCdoPayeeName())
.cdoPayeeSign(dto.getCdoPayeeSign())
.cdoPickupLat(dto.getCdoPickupLat())
.cdoPickupLon(dto.getCdoPickupLon())
.cdoPickupMin(dto.getCdoPickupMin())
.build();
order = dailyOrderRepository.save(order);
return mapToDto(order);
}
/**
* GET ALL (with paging)
*/
public Page<CustomerDailyOrderResponseDto> getAllDailyOrders(int page, int size) {
Pageable pageable = PageRequest.of(page, size);
Page<CustomerDailyOrder> orders = dailyOrderRepository.findAll(pageable);
return orders.map(this::mapToDto);
}
/**
* GET BY UUID
*/
public CustomerDailyOrderResponseDto getDailyOrderByUuid(UUID uuid) {
CustomerDailyOrder order = dailyOrderRepository.findByCdoUuid(uuid)
.orElseThrow(() -> new RuntimeException("Daily Order not found"));
return mapToDto(order);
}
/**
* GET BY CUSTOMER + DATE
*/
public CustomerDailyOrderResponseDto getDailyOrderByCustomerNo(String cusNo, LocalDate orderDate) {
CustomerDailyOrder order = dailyOrderRepository
.findByCdoCustomerNoAndCdoOrderDate(cusNo, orderDate)
.orElseThrow(() -> new RuntimeException("Order not found"));
return mapToDto(order);
}
/**
* UPDATE BY CUSTOMER + DATE
*/
@Transactional
public CustomerDailyOrderResponseDto updateDailyOrderByCustomerNoAndOrderDate(
String customerNo,
LocalDate orderDate,
CustomerDailyOrderRequestDto dto
) {
// daily order 조회
CustomerDailyOrder existing = dailyOrderRepository
.findByCdoCustomerNoAndCdoOrderDate(customerNo, orderDate)
.orElseThrow(() -> new RuntimeException("Daily Order not found"));
// 기존 updateInternal 공통 업데이트 처리
updateInternal(existing, dto);
// audit field 업데이트
existing.setCdoUpdatedAt(LocalDateTime.now());
existing.setCdoUpdatedBy(dto.getCdoLoginUser());
// 저장
dailyOrderRepository.save(existing);
return mapToDto(existing);
}
/**
* UPDATE
*/
@Transactional
public CustomerDailyOrderResponseDto updateDailyOrder(UUID uuid, CustomerDailyOrderRequestDto dto) {
CustomerDailyOrder existing = dailyOrderRepository.findByCdoUuid(uuid)
.orElseThrow(() -> new RuntimeException("Daily Order not found"));
updateInternal(existing, dto);
existing.setCdoUpdatedAt(LocalDateTime.now());
existing.setCdoUpdatedBy(dto.getCdoLoginUser());
dailyOrderRepository.save(existing);
return mapToDto(existing);
}
/**
* DELETE
*/
public void deleteDailyOrder(UUID uuid) {
CustomerDailyOrder existing = dailyOrderRepository.findByCdoUuid(uuid)
.orElseThrow(() -> new RuntimeException("Daily Order not found"));
dailyOrderRepository.delete(existing);
}
/**
* Internal Update Logic (CustomerService 동일 스타일)
*/
private void updateInternal(CustomerDailyOrder order, CustomerDailyOrderRequestDto dto) {
if (dto.getCdoOrderDate() != null) order.setCdoOrderDate(dto.getCdoOrderDate());
if (dto.getCdoOrderType() != null) order.setCdoOrderType(dto.getCdoOrderType());
if (dto.getCdoRequestNote() != null) order.setCdoRequestNote(dto.getCdoRequestNote());
if (dto.getCdoDriverId() != null) order.setCdoDriverId(dto.getCdoDriverId());
if (dto.getCdoCustomerNo() != null) order.setCdoCustomerNo(dto.getCdoCustomerNo());
if (dto.getCdoPaymentType() != null) order.setCdoPaymentType(dto.getCdoPaymentType());
if (dto.getCdoCycle() != null) order.setCdoCycle(dto.getCdoCycle());
if (dto.getCdoRate() != null) order.setCdoRate(dto.getCdoRate());
if (dto.getCdoStatus() != null) order.setCdoStatus(dto.getCdoStatus());
if (dto.getCdoVisitFlag() != null) order.setCdoVisitFlag(dto.getCdoVisitFlag());
if (dto.getCdoInputAt() != null) order.setCdoInputAt(dto.getCdoInputAt());
if (dto.getCdoEstimatedQty() != null) order.setCdoEstimatedQty(dto.getCdoEstimatedQty());
if (dto.getCdoQuantity() != null) order.setCdoQuantity(dto.getCdoQuantity());
if (dto.getCdoSludge() != null) order.setCdoSludge(dto.getCdoSludge());
if (dto.getCdoPayStatus() != null) order.setCdoPayStatus(dto.getCdoPayStatus());
if (dto.getCdoPayAmount() != null) order.setCdoPayAmount(dto.getCdoPayAmount());
if (dto.getCdoPayeeName() != null) order.setCdoPayeeName(dto.getCdoPayeeName());
if (dto.getCdoPayeeSign() != null) order.setCdoPayeeSign(dto.getCdoPayeeSign());
if (dto.getCdoPickupLat() != null) order.setCdoPickupLat(dto.getCdoPickupLat());
if (dto.getCdoPickupLon() != null) order.setCdoPickupLon(dto.getCdoPickupLon());
if (dto.getCdoPickupMin() != null) order.setCdoPickupMin(dto.getCdoPickupMin());
}
/**
* ENTITY RESPONSE DTO
*/
public CustomerDailyOrderResponseDto mapToDto(CustomerDailyOrder order) {
if (order == null) return null;
return CustomerDailyOrderResponseDto.builder()
.cdoUuid(order.getCdoUuid())
.cdoOrderDate(order.getCdoOrderDate())
.cdoOrderType(order.getCdoOrderType())
.cdoRequestNote(order.getCdoRequestNote())
.cdoDriverId(order.getCdoDriverId())
.cdoCustomerNo(order.getCdoCustomerNo())
.cdoPaymentType(order.getCdoPaymentType())
.cdoCycle(order.getCdoCycle())
.cdoRate(order.getCdoRate())
.cdoCreatedAt(order.getCdoCreatedAt())
.cdoCreatedBy(order.getCdoCreatedBy())
.cdoUpdatedAt(order.getCdoUpdatedAt())
.cdoUpdatedBy(order.getCdoUpdatedBy())
.cdoStatus(order.getCdoStatus())
.cdoVisitFlag(order.getCdoVisitFlag())
.cdoInputAt(order.getCdoInputAt())
.cdoEstimatedQty(order.getCdoEstimatedQty())
.cdoQuantity(order.getCdoQuantity())
.cdoSludge(order.getCdoSludge())
.cdoPayStatus(order.getCdoPayStatus())
.cdoPayAmount(order.getCdoPayAmount())
.cdoPayeeName(order.getCdoPayeeName())
.cdoPayeeSign(order.getCdoPayeeSign())
.cdoPickupLat(order.getCdoPickupLat())
.cdoPickupLon(order.getCdoPickupLon())
.cdoPickupMin(order.getCdoPickupMin())
.build();
}
}

View File

@ -14,7 +14,6 @@ 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;
@ -228,16 +227,15 @@ public class CustomerService {
CustomerResponseDto response = updateCustomerInternal(oldCustomer, newCustomer);
// 4. 변경 비교 (old vs new)
String misLoginUser = newCustomer.getCusLoginUser(); // todo: 내부 loginId 변경
String loginId = SecurityContextHolder.getContext().getAuthentication().getName(); // 현재는 MIS login user
compareAndLogChanges(beforeUpdate, oldCustomer, misLoginUser, loginId);
String misLoginUser = newCustomer.getCusLoginUser();
compareAndLogChanges(beforeUpdate, oldCustomer, misLoginUser);
return response;
}
// set change log
private void compareAndLogChanges(Customer oldData, Customer newData, String changedBy, String createdBy) {
private void compareAndLogChanges(Customer oldData, Customer newData, String changedBy) {
// 필드 DB 컬럼 매핑
Map<String, String> fieldToColumn = Map.ofEntries(
@ -299,7 +297,6 @@ public class CustomerService {
.eclEffectiveDate(LocalDate.now())
.eclChangedBy(changedBy)
.eclChangedAt(LocalDateTime.now())
.eclCreatedBy(changedBy)
.build()
);
}

View File

@ -2,14 +2,15 @@ package com.goi.erp.token;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.data.domain.AuditorAware;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import jakarta.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.security.Key;
/**
* auth-service에서 발급한 JWT 토큰 기반으로 현재 사용자(empId) 가져오는 AuditorAware 구현체
@ -18,7 +19,7 @@ import java.util.Optional;
* - SecurityContextHolder 없이도 동작 가능
* - HttpServletRequest에서 Authorization 헤더를 읽어 토큰 파싱
*/
public class ApplicationAuditAware implements AuditorAware<Integer> {
public class ApplicationAuditAware implements AuditorAware<String> {
private final String jwtSecret;
@ -31,7 +32,7 @@ public class ApplicationAuditAware implements AuditorAware<Integer> {
* @return Optional<Integer> - empId가 없거나 토큰이 유효하지 않으면 Optional.empty()
*/
@Override
public Optional<Integer> getCurrentAuditor() {
public Optional<String> getCurrentAuditor() {
HttpServletRequest request = getCurrentHttpRequest();
if (request == null) {
return Optional.empty();
@ -44,18 +45,22 @@ public class ApplicationAuditAware implements AuditorAware<Integer> {
try {
// JWT 파싱
byte[] keyBytes = Decoders.BASE64.decode(jwtSecret);
Key key = Keys.hmacShaKeyFor(keyBytes);
Claims claims = Jwts.parserBuilder()
// HMAC SHA 객체 생성 (secret 길이와 안전성 체크)
.setSigningKey(Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8)))
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody();
// 토큰에 empId 클레임이 있어야
Integer empId = claims.get("empId", Integer.class);
return Optional.ofNullable(empId);
// 토큰에 loginId 클레임이 있어야
String loginId = claims.get("loginId", String.class);
return Optional.ofNullable(loginId);
} catch (Exception e) {
// 토큰 파싱/검증 실패 Optional.empty() 반환
e.printStackTrace(); // 🔥 예외 확인
System.out.println("JWT Error: " + e.getMessage());
return Optional.empty();
}
}