Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
2eb51f7
[UPLUS-57] 할인 추가 제거 구현(CONTROLLER 구현중)
arlen02-01 Jan 14, 2026
cf3701d
[UPLUS-57] 할인 추가삭제 기능 추가/developer브랜치와 병합 및 오류 수정
arlen02-01 Jan 14, 2026
2fd535a
UPLUS-57 refactor: 마스킹전화번호가 db에 저장되는 오류 수정
arlen02-01 Jan 14, 2026
7632ca3
UPLUS-57 refactor: 할인 도메인 모델 정리
arlen02-01 Jan 14, 2026
4bee79d
UPLUS-57 feat: 고객 응답 DTO 추가
arlen02-01 Jan 14, 2026
ddffb27
UPLUS-57 refactor: 할인 응답 DTO 조정
arlen02-01 Jan 14, 2026
2545b0a
UPLUS-57 refactor: 할인 조회 로직 정리
arlen02-01 Jan 14, 2026
24575e3
UPLUS-57 refactor: 고객 컨트롤러 응답 변경
arlen02-01 Jan 14, 2026
37f4796
Update src/main/java/com/project/core/infra/entity/discount/DiscountP…
arlen02-01 Jan 14, 2026
7376af3
Update src/main/java/com/project/core/service/SubscriptionService.java
arlen02-01 Jan 14, 2026
2328c0b
Update src/main/java/com/project/core/infra/entity/discount/enums/Sta…
arlen02-01 Jan 14, 2026
12c2f33
Update src/main/java/com/project/core/controller/dto/response/Subscri…
arlen02-01 Jan 14, 2026
c2729ba
Update src/main/java/com/project/core/controller/dto/response/Custome…
arlen02-01 Jan 14, 2026
7ec6c00
Update src/main/java/com/project/core/infra/entity/discount/enums/Act…
arlen02-01 Jan 14, 2026
a2c0bfd
Update src/main/java/com/project/core/service/DiscountService.java
arlen02-01 Jan 14, 2026
df85646
Update src/main/java/com/project/global/exception/code/domain/core/Co…
arlen02-01 Jan 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 50 additions & 11 deletions src/main/java/com/project/core/controller/CustomerController.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,62 @@
package com.project.core.controller;

import com.project.core.controller.dto.request.FindCustomerRequest;
import java.util.List;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import com.project.core.controller.dto.request.ChangeEmailRequest;
import com.project.core.controller.dto.request.ChangeGradeRequest;
import com.project.core.controller.dto.response.ChangeEmailResponse;
import com.project.core.controller.dto.response.ChangeGradeResponse;
import com.project.core.controller.dto.response.CustomerResponse;
import com.project.core.infra.entity.customer.Customer;
import com.project.core.service.CustomerService;

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class CustomerController {
private final CustomerService customerService;

@GetMapping
public Long save(@RequestBody FindCustomerRequest request) {
Customer customer = customerService.loadByContactEnc(request.contactEnc());
return customer.getCustomerId();
}
private final CustomerService customerService;

/**
* 고객 조회 (전화번호 기준)
*/
@GetMapping
public ResponseEntity<List<CustomerResponse>> loadByContactEnc(@RequestParam String contactEnc) {
List<Customer> customers = customerService.loadByContactEnc(contactEnc);

List<CustomerResponse> response = customers.stream()
.map(CustomerResponse::from)
.toList();

return ResponseEntity.ok(response);
}
Comment thread
arlen02-01 marked this conversation as resolved.

/**
* 이메일 변경
*/
@PostMapping("/{userId}/email")
public ResponseEntity<ChangeEmailResponse> changeEmail(
@PathVariable Long userId,
@RequestBody ChangeEmailRequest request
) {
ChangeEmailResponse response = customerService.changeEmailEnc(userId, request);
return ResponseEntity.ok(response);
}

/**
* 고객 등급 변경
*/
@PostMapping("/{userId}/grade")
public ResponseEntity<ChangeGradeResponse> changeGrade(
@PathVariable Long userId,
@RequestBody ChangeGradeRequest request
) {
ChangeGradeResponse response = customerService.changeUserGrade(userId, request);
return ResponseEntity.ok(response);
}
}
99 changes: 99 additions & 0 deletions src/main/java/com/project/core/controller/DiscountController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.project.core.controller;

import java.util.List;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.project.core.controller.dto.response.SubscriptionDiscountResponse;
import com.project.core.infra.entity.discount.SubscriptionDiscount;
import com.project.core.service.DiscountService;

import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping("/discounts")
@RequiredArgsConstructor
public class DiscountController {

private final DiscountService discountService;

/**
* 회선(subId)에 적용된 할인 목록 조회
* GET /discounts/subscriptions/{subId}
*/
@GetMapping("/subscriptions/{subId}")
public ResponseEntity<List<SubscriptionDiscountResponse>> getDiscountsBySubscription(@PathVariable Long subId) {
List<SubscriptionDiscount> discounts = discountService.loadRequiredBySubId(subId);

List<SubscriptionDiscountResponse> response = discounts.stream()
.map(SubscriptionDiscountResponse::from)
.toList();

return ResponseEntity.ok(response);
}

/**
* 회선(subId)에 할인 정책(discountId) 추가(적용)
* POST /discounts
*/
@PostMapping
public ResponseEntity<CreateDiscountResponse> addDiscount(@RequestBody CreateDiscountRequest request) {
Long sdId = discountService.addDiscount(request.getSubId(), request.getDiscountId());
return ResponseEntity.status(HttpStatus.CREATED).body(new CreateDiscountResponse(sdId));
}

/**
* 기존 할인(sdId)을 종료하고, 새로운 할인 정책(discountId)로 변경
* PATCH /discounts/{sdId}
*/
@PatchMapping("/{sdId}")
public ResponseEntity<ChangeDiscountResponse> changeDiscount(
@PathVariable Long sdId,
@RequestBody ChangeDiscountRequest request
) {
Long newSdId = discountService.changeDiscount(request.getDiscountId(), sdId);
return ResponseEntity.ok(new ChangeDiscountResponse(newSdId));
}

// ===== DTOs =====

public static class CreateDiscountRequest {
private Long subId;
private Long discountId;

public Long getSubId() { return subId; }
public Long getDiscountId() { return discountId; }

public void setSubId(Long subId) { this.subId = subId; }
public void setDiscountId(Long discountId) { this.discountId = discountId; }
}
Comment thread
arlen02-01 marked this conversation as resolved.

public static class CreateDiscountResponse {
private final Long sdId;

public CreateDiscountResponse(Long sdId) { this.sdId = sdId; }
public Long getSdId() { return sdId; }
}

public static class ChangeDiscountRequest {
private Long discountId;

public Long getDiscountId() { return discountId; }
public void setDiscountId(Long discountId) { this.discountId = discountId; }
}

public static class ChangeDiscountResponse {
private final Long newSdId;

public ChangeDiscountResponse(Long newSdId) { this.newSdId = newSdId; }
public Long getNewSdId() { return newSdId; }
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package com.project.core.controller.dto.request;

public record ChangeEmailRequest(String emailEnc) {}
public record ChangeEmailRequest(String email) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.project.core.controller.dto.response;

import com.project.core.infra.entity.customer.Customer;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class CustomerResponse {

private Long customerId;
private String name;
private String grade;

// 필요하면 마스킹된 연락처만 제공(원본/암호화값은 노출 금지)
private String maskedContact;

public static CustomerResponse from(Customer c) {
return CustomerResponse.builder()
.customerId(c.getCustomerId())
.name(c.getName())
.grade(String.valueOf(c.getGrade())) // grade가 enum이면 적절히 변환
// maskedContact는 "복호화 가능한 원본"이 있을 때만 넣는 걸 권장
.maskedContact(null)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.project.core.controller.dto.response;

import java.math.BigDecimal;
import java.time.LocalDateTime;

import com.project.core.infra.entity.discount.SubscriptionDiscount;
import com.project.core.infra.entity.discount.enums.DiscountType;
import com.project.core.infra.entity.discount.enums.Status;
import com.project.core.infra.entity.discount.enums.TargetScope;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class SubscriptionDiscountResponse {

private Long sdId;
private Long subId;
private String maskedPhoneNumber;

private Long discountId;
private DiscountType discountType;
private BigDecimal value;
private TargetScope targetScope;

private LocalDateTime startDate;
private LocalDateTime endDate;
private Status status;

public static SubscriptionDiscountResponse from(SubscriptionDiscount sd) {

String phone = sd.getSubscription().getPhoneNumber();

return SubscriptionDiscountResponse.builder()
.sdId(sd.getSdId())
.subId(sd.getSubscription().getSubId())
.maskedPhoneNumber(maskPhone(phone))

.discountId(sd.getDiscountPolicy().getDiscountId())
.discountType(sd.getDiscountType())
.value(sd.getValue())
.targetScope(sd.getTargetScope())

.startDate(sd.getStartDate())
.endDate(sd.getEndDate())
.status(sd.getStatus())
.build();
}

/**
* 010-1234-1212 -> 010-**12-**12
* 01012341212 -> 010-**12-**12
*/
private static String maskPhone(String phone) {
if (phone == null || phone.isBlank()) return null;

// 숫자만 추출
String digits = phone.replaceAll("\\D", "");
if (digits.length() != 11) {
return "****"; // 예상 못 한 형식은 전체 마스킹
}

String p1 = digits.substring(0, 3); // 010
String p2 = digits.substring(3, 7); // 1234
String p3 = digits.substring(7, 11); // 1212

// **12 / **12
String masked2 = "**" + p2.substring(2);
String masked3 = "**" + p3.substring(2);

return String.format("%s-%s-%s", p1, masked2, masked3);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.project.core.infra.entity.discount;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import com.project.core.infra.entity.discount.enums.Active;
import com.project.core.infra.entity.discount.enums.Category;
import com.project.core.infra.entity.discount.enums.DiscountType;
import com.project.core.infra.entity.discount.enums.TargetScope;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "discount_policy")
public class DiscountPolicy {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "discount_id")
private Long discountId;

@Column(name = "name", nullable = false)
private String name;

@Column(name = "discount_type", nullable = false)
private DiscountType discountType;

@Column(name = "value", nullable = false)
private BigDecimal value;

@Column(name = "category", nullable = false)
private Category category;

@Column(name = "target_scope", nullable = false)
private TargetScope targetScope;

@Column(name = "active", nullable = false)
private Active active;
@OneToMany(mappedBy = "discountPolicy")
private List<SubscriptionDiscount> discountHistory = new ArrayList<>();
}
Loading
Loading