Skip to content

Commit

Permalink
Merge pull request #27 from C4-ComeTrue/feature/opixxx_step3
Browse files Browse the repository at this point in the history
Feature/opixxx step3
  • Loading branch information
opixxx authored Feb 17, 2025
2 parents b560afc + d5db300 commit ee5f3b5
Show file tree
Hide file tree
Showing 18 changed files with 870 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.c4marathon.assignment.global.util;

import java.security.SecureRandom;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class SettlementUtil {
private static final SecureRandom SECURE_RANDOM = new SecureRandom();

public static int getRandomInt(int range) {
return SECURE_RANDOM.nextInt(range);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package org.c4marathon.assignment.settlement.domain;

import static jakarta.persistence.FetchType.*;

import java.util.ArrayList;
import java.util.List;

import org.c4marathon.assignment.global.entity.BaseEntity;

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

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Settlement extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "settlement_id")
private Long id;

private Long requestAccountId; //정산 요청한 계좌 ID

private int totalAmount; //총 정산 금액

private int amount; //내 정산 금액

@Enumerated(EnumType.STRING)
private SettlementType type;

@OneToMany(mappedBy = "settlement", fetch = LAZY, cascade = CascadeType.ALL)
private List<SettlementDetail> settlementDetails = new ArrayList<>();

@Builder
private Settlement(Long requestAccountId, int totalAmount, SettlementType type) {
this.requestAccountId = requestAccountId;
this.totalAmount = totalAmount;
this.type = type;
}

public static Settlement create(Long requestAccountId, int totalAmount, SettlementType type) {
return Settlement.builder()
.requestAccountId(requestAccountId)
.totalAmount(totalAmount)
.type(type)
.build();
}

public void setAmount(int amount) {
this.amount = amount;
}

public void addSettlementDetail(SettlementDetail settlementDetail) {
this.settlementDetails.add(settlementDetail);
settlementDetail.setSettlement(this);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.c4marathon.assignment.settlement.domain;

import org.c4marathon.assignment.global.entity.BaseEntity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class SettlementDetail extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "settlement_detail_id")
private Long id;

private Long accountId;

private int amount;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "settlement_id", nullable = false)
private Settlement settlement;

@Builder
private SettlementDetail(Settlement settlement, Long accountId, int amount) {
this.settlement = settlement;
this.accountId = accountId;
this.amount = amount;
}

public static SettlementDetail create(Settlement settlement, Long accountId, int amount) {
SettlementDetail settlementDetail = SettlementDetail.builder()
.accountId(accountId)
.amount(amount)
.build();
settlement.addSettlementDetail(settlementDetail);
return settlementDetail;
}

public void setSettlement(Settlement settlement) {
this.settlement = settlement;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.c4marathon.assignment.settlement.domain;

public enum SettlementType {
EQUAL,
RANDOM
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.c4marathon.assignment.settlement.domain.repository;

import java.util.List;

import org.c4marathon.assignment.settlement.domain.SettlementDetail;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface SettlementDetailRepository extends JpaRepository<SettlementDetail, Long> {

@Query("""
SELECT sd
FROM SettlementDetail sd
JOIN FETCH sd.settlement s
WHERE sd.accountId = :accountId
""")
List<SettlementDetail> findByAccountId(@Param("accountId") Long accountId);

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.c4marathon.assignment.settlement.domain.repository;

import java.util.List;

import org.c4marathon.assignment.settlement.domain.Settlement;
import org.springframework.data.jpa.repository.JpaRepository;

public interface SettlementRepository extends JpaRepository<Settlement, Long> {
List<Settlement> findByRequestAccountId(Long requestAccountId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.c4marathon.assignment.settlement.dto;

public record ReceivedSettlementResponse(
Long settlementId,
Long requestAccountId,
int totalAmount,
Long myAccountId,
int mySettlementAmount
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.c4marathon.assignment.settlement.dto;

public record SettlementDetailInfo(
Long settlementDetailId,
Long accountId,
int amount
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.c4marathon.assignment.settlement.dto;

import java.util.List;

import org.c4marathon.assignment.settlement.domain.SettlementType;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PositiveOrZero;

public record SettlementRequest(

@PositiveOrZero
@Max(value = 100, message = "100명까지 정산이 가능합니다.")
int totalNumber,

@PositiveOrZero
int totalAmount,

@NotNull(message = "정산 인원을 추가해주세요.")
List<Long> accountIds,

@NotNull(message = "정산 타입을 선택해주세요.")
SettlementType type

) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.c4marathon.assignment.settlement.dto;

import java.util.List;


public record SettlementResponse(
Long settlementId,
Long requestAccountId,
int totalAmount,
List<SettlementDetailInfo> members
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.c4marathon.assignment.settlement.presentation;

import java.util.List;

import org.c4marathon.assignment.global.annotation.Login;
import org.c4marathon.assignment.global.session.SessionMemberInfo;
import org.c4marathon.assignment.settlement.dto.ReceivedSettlementResponse;
import org.c4marathon.assignment.settlement.dto.SettlementRequest;
import org.c4marathon.assignment.settlement.dto.SettlementResponse;
import org.c4marathon.assignment.settlement.service.SettlementService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
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 jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class SettlementController {
private final SettlementService settlementService;

@PostMapping("/settle")
public ResponseEntity<Void> settle(
@Login SessionMemberInfo loginMember,
@RequestBody @Valid SettlementRequest request
) {
settlementService.createSettlement(loginMember.accountId(), request);
return ResponseEntity.ok().build();
}

@GetMapping("/settlements/requested")
public ResponseEntity<List<SettlementResponse>> getRequestedSettlements(@Login SessionMemberInfo loginMember) {
return ResponseEntity.ok().body(settlementService.getRequestedSettlements(loginMember.accountId()));
}

@GetMapping("/settlements/received")
public ResponseEntity<List<ReceivedSettlementResponse>> getReceivedSettlements(@Login SessionMemberInfo loginMember) {
return ResponseEntity.ok().body(settlementService.getReceivedSettlements(loginMember.accountId()));
}
}
Loading

0 comments on commit ee5f3b5

Please sign in to comment.