Skip to content

Commit

Permalink
feat: 계약, 납입 API 추가 및 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
hongkikii authored Dec 6, 2023
2 parents 9fcc310 + c54ad15 commit b530ab4
Show file tree
Hide file tree
Showing 15 changed files with 245 additions and 37 deletions.
16 changes: 14 additions & 2 deletions ddl.sql
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ VALUES ('id1', '김철수', '회사원', '01012345678', '1997-11-19', '남', '
('id6', '김마바', '가정주부', '01067891234', '1997-11-19', '', '서울특별시 서대문구 거북골로 67'),
('id7', '김바사', '프리랜서', '01078912345', '1997-11-19', '', '서울특별시 서대문구 거북골로 78'),
('id8', '김사아', '자영업자', '01089123456', '1997-11-09', '', '서울특별시 서대문구 거북골로 89'),
('id9', '김아자', '예술가', '01091234567', '1997-11-19', '', '서울특별시 서대문구 거북골로 90');
('id9', '김아자', '예술가', '01091234567', '1997-11-19', '', '서울특별시 서대문구 거북골로 90'),
('id10', '김자차', '자영업자', '01013243546', '1999-03-23', '', '서울특별시 서대문구 거북골로 91');

INSERT INTO Contract (insuranceID, insurancePeriod, premium, paymentCycle, paymentPeriod, maxCompensation, dateOfSubscription, dateOfMaturity, maturity, resurrection, cancellation, customerID)
VALUES
Expand All @@ -251,7 +252,18 @@ VALUES
(1, '10년', 200000, 'QUARTERLY_PAYMENT', '36개월', 3000000, '2019-08-29', '2024-03-23', 1, 1, 0, 3),
(2, '10년', 100000, 'MONTHLY_PAYMENT', '12개월', 3000000, '2019-03-29', '2024-03-23', 1, 0, 0, 4),
(1, '10년', 200000, 'QUARTERLY_PAYMENT', '36개월', 3000000, '2019-02-22', '2024-03-23', 0, 1, 0, 5),
(1, '10년', 200000, 'MONTHLY_PAYMENT', '12개월', 3000000, '2019-01-29', '2024-03-23', 1, 1, 0, 6);
(1, '10년', 200000, 'QUARTERLY_PAYMENT', '36개월', 3000000, '2008-02-22', '2018-02-22', 1, 1, 1, 10),
(2, '10년', 100000, 'MONTHLY_PAYMENT', '12개월', 3000000, '2009-03-23', '2019-03-23', 1, 1, 1, 10),
(3, '5년', 500000, 'MONTHLY_PAYMENT', '12개월', 3000000, '2010-02-22', '2015-02-22', 1, 1, 1, 10),
(9, '1년', 300000, 'QUARTERLY_PAYMENT', '36개월', 20000000, '2019-02-22', '2020-02-22', 1, 1, 0, 10),
(13, '1년', 120000, 'MONTHLY_PAYMENT', '12개월', 5000000, '2020-06-07', '2021-06-07', 1, 1, 0, 10),
(14, '3년', 50000, 'MONTHLY_PAYMENT', '12개월', 1000000, '2020-05-19', '2023-05-19', 1, 1, 0, 10),
(11, '15년', 800000, 'QUARTERLY_PAYMENT', '36개월', 200000000, '2022-04-30', '2037-04-30', 0, 0, 0, 10),
(18, '평생', 1500000, 'QUARTERLY_PAYMENT', '36개월', 800000000, '2019-02-22', '2099-12-31', 0, 0, 0, 10),
(8, '5년', 80000, 'MONTHLY_PAYMENT', '12개월', 3000000, '2019-08-02', '2024-08-02', 0, 0, 0, 10),
(10, '8년', 3000000, 'QUARTERLY_PAYMENT', '36개월', 200000000, '2020-09-30', '2028-09-30', 0, 0, 1, 10),
(12, '평생', 2000000, 'QUARTERLY_PAYMENT', '36개월', 1000000000, '2023-12-06', '2099-12-31', 0, 0, 1, 10),
(19, '2년', 180000, 'MONTHLY_PAYMENT', '12개월', 15000000, '2023-12-06', '2025-12-06', 0, 0, 1, 10);

INSERT INTO Payment (customerID, insuranceID, ContractID, dateOfPayment, whetherPayment)
VALUES
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package aplus.insurancesystem.domain.contract.controller;

import aplus.insurancesystem.common.dto.SuccessResponse;
import aplus.insurancesystem.domain.contract.dto.response.ContractCancelContentResponse;
import aplus.insurancesystem.domain.contract.dto.response.ContractAllInfoResponse;
import aplus.insurancesystem.domain.contract.dto.response.ContractCancelResponse;
import aplus.insurancesystem.domain.contract.dto.response.ContractDetailResponse;
import aplus.insurancesystem.domain.contract.service.ContractService;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -17,6 +19,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

Expand Down Expand Up @@ -58,4 +61,40 @@ public ResponseEntity<SuccessResponse<List<ContractAllInfoResponse>>> getContrac
return SuccessResponse.of(contractService.getContractList(customerId))
.asHttp(HttpStatus.OK);
}

@Operation(summary = "계약 해지 정보 조회", description = "계약 해지: 계약 중도/만기 해지 정보 조회 API")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "해지 시 예상 정보 반환"),
@ApiResponse(
responseCode = "404",
description = "C001: id에 해당하는 계약을 찾을 수 없습니다.",
content = @Content(schema = @Schema(hidden = true)))
})
@GetMapping("/{id}/cancel-content")
public ResponseEntity<SuccessResponse<ContractCancelContentResponse>> getCancelContent(
@Parameter(description = "계약 id", in = ParameterIn.PATH)
@PathVariable("id") Long contractId) {
return SuccessResponse.of(contractService.getCancelContent(contractId))
.asHttp(HttpStatus.OK);
}

@Operation(summary = "계약 해지", description = "계약 해지: 계약 중도/만기 해지 API")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "해지 시 필요 정보 반환"),
@ApiResponse(
responseCode = "404",
description = "C001: id에 해당하는 계약을 찾을 수 없습니다.",
content = @Content(schema = @Schema(hidden = true)))
})
@PostMapping("/{id}/cancel")
public ResponseEntity<SuccessResponse<ContractCancelResponse>> cancel(
@Parameter(description = "계약 id", in = ParameterIn.PATH)
@PathVariable("id") Long contractId) {
return SuccessResponse.of(contractService.cancel(contractId))
.asHttp(HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
@AllArgsConstructor(access = lombok.AccessLevel.PRIVATE)
public class ContractAllInfoResponse {
@Schema(description = "계약 id", requiredMode = RequiredMode.REQUIRED)
private Long id;
private String insuranceName;
private String insuranceType;
private Integer premium;
private String paymentPeriod;
private Boolean maturity;
private Boolean resurrection;
private Boolean cancellation;
private final Long id;
private final String insuranceName;
private final String insuranceType;
private final Integer premium;
private final String paymentPeriod;
private final Boolean maturity;
private final Boolean resurrection;
private final Boolean cancellation;

public static ContractAllInfoResponse of(Contract contract) {
return new ContractAllInfoResponse(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package aplus.insurancesystem.domain.contract.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@Schema(description = "계약 해지 정보 Response")
@AllArgsConstructor(access = lombok.AccessLevel.PRIVATE)
public class ContractCancelContentResponse {
private final String insuranceName;
private final String customerName;
private final String totalPremiumPaid;
private final String refundAmount;

public static ContractCancelContentResponse of(String insuranceName, String customerName,
String totalPremiumPaid, String refundAmount) {
return new ContractCancelContentResponse(insuranceName, customerName, totalPremiumPaid, refundAmount);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package aplus.insurancesystem.domain.contract.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@Schema(description = "계약 해지 Response")
@AllArgsConstructor(access = lombok.AccessLevel.PRIVATE)
public class ContractCancelResponse {
@Schema(description = "이미 해지된 계약인지 여부")
private final Boolean isAlreadyCancelled;

public static ContractCancelResponse of(Boolean isAlreadyCancelled) {
return new ContractCancelResponse(isAlreadyCancelled);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@
public class ContractDetailResponse {

@Schema(description = "계약 id")
private Long id;
private String insuranceName;
private String insuranceType;
private String insurancePeriod;
private Integer premium;
private PaymentCycle paymentCycle;
private String paymentPeriod;
private Integer maxCompensation;
private final Long id;
private final String insuranceName;
private final String insuranceType;
private final String insurancePeriod;
private final Integer premium;
private final PaymentCycle paymentCycle;
private final String paymentPeriod;
private final Integer maxCompensation;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate dateOfSubscription;
private final LocalDate dateOfSubscription;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate dateOfMaturity;
private final LocalDate dateOfMaturity;
private final Boolean Maturity;
private final Boolean Cancellation;

public static ContractDetailResponse of(Contract contract) {
return new ContractDetailResponse(
Expand All @@ -40,6 +42,8 @@ public static ContractDetailResponse of(Contract contract) {
contract.getPaymentPeriod(),
contract.getMaxCompensation(),
contract.getDateOfSubscription(),
contract.getDateOfMaturity());
contract.getDateOfMaturity(),
contract.getMaturity(),
contract.getCancellation());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package aplus.insurancesystem.domain.contract.service;

public interface ContractQueryService {
Integer getPremium(Long contractId);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package aplus.insurancesystem.domain.contract.service;

import aplus.insurancesystem.domain.contract.exception.ContractNotFoundException;
import aplus.insurancesystem.domain.contract.repository.ContractRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class ContractQueryServiceImpl implements ContractQueryService {

private final ContractRepository contractRepository;

@Override
public Integer getPremium(Long contractId) {
return contractRepository.findById(contractId)
.orElseThrow(ContractNotFoundException::new).getPremium();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import aplus.insurancesystem.domain.Insurance.entity.insurauceApplication.InsuranceApplication;
import aplus.insurancesystem.domain.contract.dto.response.ContractAllInfoResponse;
import aplus.insurancesystem.domain.contract.dto.response.ContractCancelContentResponse;
import aplus.insurancesystem.domain.contract.dto.response.ContractCancelResponse;
import aplus.insurancesystem.domain.contract.dto.response.ContractDetailResponse;
import aplus.insurancesystem.domain.contract.entity.Contract;
import aplus.insurancesystem.domain.customer.entity.customer.Customer;
Expand All @@ -13,6 +15,6 @@ public interface ContractService {
void createContract(InsuranceApplication insuranceApplication);
ContractDetailResponse getContractDetail(Long contractId);
List<ContractAllInfoResponse> getContractList(Long customerId);

Integer getPremium(Long contractId);
ContractCancelContentResponse getCancelContent(Long contractId);
ContractCancelResponse cancel(Long contractId);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package aplus.insurancesystem.domain.contract.service;

import aplus.insurancesystem.domain.contract.dto.response.ContractCancelContentResponse;
import aplus.insurancesystem.domain.contract.dto.response.ContractCancelResponse;
import aplus.insurancesystem.domain.payment.service.PaymentService;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -22,10 +27,20 @@
public class ContractServiceImpl implements ContractService {

private final ContractRepository contractRepository;
private final PaymentService paymentService;

@Override
@Transactional
public void createContract(InsuranceApplication insuranceApplication) {
LocalDate dateOfSubscription = insuranceApplication.getCreatedAt();
String insurancePeriod = insuranceApplication.getInsurancePeriod();
LocalDate dateOfMaturity = LocalDate.of(2099, 12, 31);
if (insurancePeriod.contains("년")) {
int endIndex = insurancePeriod.indexOf("년");
int extractedInsurancePeriod = Integer.parseInt(insurancePeriod.substring(0, endIndex));
dateOfMaturity = dateOfSubscription.plusYears(extractedInsurancePeriod);
}

Contract contract = Contract.builder()
.customer(insuranceApplication.getCustomer())
.insurance(insuranceApplication.getInsurance())
Expand All @@ -34,13 +49,14 @@ public void createContract(InsuranceApplication insuranceApplication) {
.paymentCycle(insuranceApplication.getPaymentCycle())
.maxCompensation(insuranceApplication.getMaxCompensation())
.dateOfSubscription(insuranceApplication.getCreatedAt())
.dateOfMaturity(LocalDate.parse("2099-12-31"))
.dateOfMaturity(dateOfMaturity)
.paymentPeriod(insuranceApplication.getPaymentPeriod())
.maturity(false)
.resurrection(false)
.cancellation(false)
.build();
contractRepository.save(contract);
paymentService.createPayment(contract);
}

@Override
Expand All @@ -64,8 +80,41 @@ public List<ContractAllInfoResponse> getContractList(Long customerId) {
}

@Override
public Integer getPremium(Long contractId) {
return contractRepository.findById(contractId)
.orElseThrow(ContractNotFoundException::new).getPremium();
public ContractCancelContentResponse getCancelContent(Long contractId) {
Contract contract = contractRepository.findById(contractId)
.orElseThrow(() -> new ContractNotFoundException());
Double totalPremiumPaid = paymentService.getTotalPremiumPaid(contractId);
Double refundAmount;
if (contract.getMaturity()) {
refundAmount = totalPremiumPaid * 0.8;
}
else {
refundAmount = (totalPremiumPaid - (totalPremiumPaid * 0.6) + totalPremiumPaid * 0.3);
}
return ContractCancelContentResponse.of(contract.getInsurance().getInsuranceName(),
contract.getCustomer().getCustomerName(),
String.valueOf(totalPremiumPaid),
String.valueOf(refundAmount));
}

@Override
@Transactional
public ContractCancelResponse cancel(Long contractId) {
Contract contract = contractRepository.findById(contractId)
.orElseThrow(() -> new ContractNotFoundException());
if (contract.getCancellation()) {
return ContractCancelResponse.of(true);
}
contract.setCancellation(true);
return ContractCancelResponse.of(false);
}

@Scheduled(cron = "0 0 0 * * ?")
@Transactional
public void updateMaturity() {
contractRepository.findAll()
.stream()
.filter(contract -> contract.getDateOfMaturity().isEqual(LocalDate.now()))
.forEach(contract -> contract.setMaturity(true));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
@AllArgsConstructor(access = lombok.AccessLevel.PRIVATE)
public class PaymentInfoResponse {
@Schema(description = "납입 id")
private Long id;
private Integer premium;
private Boolean whetherPayment;
private final Long id;
private final Integer premium;
private final Boolean whetherPayment;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate stringDateOfPayment;
private final LocalDate stringDateOfPayment;

public static PaymentInfoResponse of(Payment payment, Integer premium) {
return new PaymentInfoResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
@AllArgsConstructor(access = lombok.AccessLevel.PRIVATE)
public class PaymentUpdateResponse {
@Schema(description = "이전에 납입이 완료되었는지 여부")
boolean isExistedPayment;
private final Boolean isExistedPayment;

public static PaymentUpdateResponse of(Boolean isExistedPayment) {
return new PaymentUpdateResponse(isExistedPayment);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
Expand Down Expand Up @@ -56,6 +57,7 @@ public class Payment {
private LocalDate dateOfPayment;
private Boolean whetherPayment;

@Builder
public Payment(Customer customer, Insurance insurance, Contract contract,
LocalDate dateOfPayment, Boolean whetherPayment) {
this.customer = customer;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package aplus.insurancesystem.domain.payment.service;

import aplus.insurancesystem.domain.Insurance.entity.insurauceApplication.InsuranceApplication;
import aplus.insurancesystem.domain.contract.entity.Contract;
import aplus.insurancesystem.domain.payment.dto.PaymentInfoResponse;
import aplus.insurancesystem.domain.payment.dto.PaymentUpdateResponse;
import java.util.List;

public interface PaymentService {
// 납입 생성

void createPayment(Contract contract);
List<PaymentInfoResponse> getPaymentList(Long contractId);

Double getTotalPremiumPaid(Long contractId);
PaymentUpdateResponse updatePayment(Long paymentId);
}
Loading

0 comments on commit b530ab4

Please sign in to comment.