From d0fb4a972a01484d4193ef5d1e7cd5acd7113a97 Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 09:59:40 +0900 Subject: [PATCH 01/12] =?UTF-8?q?feat:=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/estdelivery/domain/Account.kt | 18 ++++++++++++++++++ .../example/estdelivery/domain/Transaction.kt | 12 ++++++++++++ .../com/example/estdelivery/domain/User.kt | 6 ++++++ 3 files changed, 36 insertions(+) create mode 100644 src/main/kotlin/com/example/estdelivery/domain/Account.kt create mode 100644 src/main/kotlin/com/example/estdelivery/domain/Transaction.kt create mode 100644 src/main/kotlin/com/example/estdelivery/domain/User.kt diff --git a/src/main/kotlin/com/example/estdelivery/domain/Account.kt b/src/main/kotlin/com/example/estdelivery/domain/Account.kt new file mode 100644 index 0000000..6ed8aee --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/domain/Account.kt @@ -0,0 +1,18 @@ +package com.example.estdelivery.domain + +import java.math.BigDecimal + +data class Account( + val userId: Long, + val accountNumber: String, + var balance: BigDecimal, + val id: Long? = null +) { + fun deposit(amount: BigDecimal) { + balance += amount + } + + fun withdraw(amount: BigDecimal) { + balance -= amount + } +} diff --git a/src/main/kotlin/com/example/estdelivery/domain/Transaction.kt b/src/main/kotlin/com/example/estdelivery/domain/Transaction.kt new file mode 100644 index 0000000..cd55ac5 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/domain/Transaction.kt @@ -0,0 +1,12 @@ +package com.example.estdelivery.domain + +import java.math.BigDecimal +import java.time.LocalDateTime + +data class Transaction( + val id: Long, + val senderId: Long, + val receiverId: Long, + val amount: BigDecimal, + val timestamp: LocalDateTime +) diff --git a/src/main/kotlin/com/example/estdelivery/domain/User.kt b/src/main/kotlin/com/example/estdelivery/domain/User.kt new file mode 100644 index 0000000..bbe33a0 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/domain/User.kt @@ -0,0 +1,6 @@ +package com.example.estdelivery.domain + +data class User( + val name: String, + val id: Long? = null +) From 65ea3bea1a11a3bbe76cd25b57d47ea4d136cb2b Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 10:00:27 +0900 Subject: [PATCH 02/12] =?UTF-8?q?feat:=20=EC=95=A0=ED=94=8C=EB=A6=AC?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=85=98=20=EB=82=B4=EB=B6=80=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20port=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/in/ProcessTransactionUseCase.kt | 14 ++++++++++++++ .../application/port/in/RegisterAccountUseCase.kt | 5 +++++ .../application/port/in/RegisterUserUseCase.kt | 5 +++++ 3 files changed, 24 insertions(+) create mode 100644 src/main/kotlin/com/example/estdelivery/application/port/in/ProcessTransactionUseCase.kt create mode 100644 src/main/kotlin/com/example/estdelivery/application/port/in/RegisterAccountUseCase.kt create mode 100644 src/main/kotlin/com/example/estdelivery/application/port/in/RegisterUserUseCase.kt diff --git a/src/main/kotlin/com/example/estdelivery/application/port/in/ProcessTransactionUseCase.kt b/src/main/kotlin/com/example/estdelivery/application/port/in/ProcessTransactionUseCase.kt new file mode 100644 index 0000000..87cceca --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/application/port/in/ProcessTransactionUseCase.kt @@ -0,0 +1,14 @@ +package com.example.estdelivery.application.port.`in` + +import java.math.BigDecimal +import java.time.LocalDateTime + +interface ProcessTransactionUseCase { + fun process( + senderId: Long, + senderAccountId: Long, + receiverId: Long, + receiverAccountId: Long, + amount: BigDecimal + ): BigDecimal +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/application/port/in/RegisterAccountUseCase.kt b/src/main/kotlin/com/example/estdelivery/application/port/in/RegisterAccountUseCase.kt new file mode 100644 index 0000000..d5feaa3 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/application/port/in/RegisterAccountUseCase.kt @@ -0,0 +1,5 @@ +package com.example.estdelivery.application.port.`in` + +interface RegisterAccountUseCase { + fun registerAccount(userId: Long) +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/application/port/in/RegisterUserUseCase.kt b/src/main/kotlin/com/example/estdelivery/application/port/in/RegisterUserUseCase.kt new file mode 100644 index 0000000..f283c30 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/application/port/in/RegisterUserUseCase.kt @@ -0,0 +1,5 @@ +package com.example.estdelivery.application.port.`in` + +interface RegisterUserUseCase { + fun registerUser(name: String) +} \ No newline at end of file From 0598f082a1e1dd61d6c3b39cfe972815537f773d Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 10:02:04 +0900 Subject: [PATCH 03/12] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=ED=95=A0=20?= =?UTF-8?q?=EC=99=B8=EB=B6=80=20=EC=96=B4=EB=8E=81=ED=84=B0=20port=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/port/out/AccountPersistencePort.kt | 8 ++++++++ .../estdelivery/application/port/out/LoadAccountsPort.kt | 8 ++++++++ .../application/port/out/TransactionPersistencePort.kt | 4 ++++ .../application/port/out/UserPersistencePort.kt | 7 +++++++ 4 files changed, 27 insertions(+) create mode 100644 src/main/kotlin/com/example/estdelivery/application/port/out/AccountPersistencePort.kt create mode 100644 src/main/kotlin/com/example/estdelivery/application/port/out/LoadAccountsPort.kt create mode 100644 src/main/kotlin/com/example/estdelivery/application/port/out/TransactionPersistencePort.kt create mode 100644 src/main/kotlin/com/example/estdelivery/application/port/out/UserPersistencePort.kt diff --git a/src/main/kotlin/com/example/estdelivery/application/port/out/AccountPersistencePort.kt b/src/main/kotlin/com/example/estdelivery/application/port/out/AccountPersistencePort.kt new file mode 100644 index 0000000..383a489 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/application/port/out/AccountPersistencePort.kt @@ -0,0 +1,8 @@ +package com.example.estdelivery.application.port.out + +import com.example.estdelivery.domain.Account + +interface AccountPersistencePort { + fun updateAccountBalance(account: Account) + fun registerAccount(account: Account) +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/application/port/out/LoadAccountsPort.kt b/src/main/kotlin/com/example/estdelivery/application/port/out/LoadAccountsPort.kt new file mode 100644 index 0000000..b083850 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/application/port/out/LoadAccountsPort.kt @@ -0,0 +1,8 @@ +package com.example.estdelivery.application.port.out + +import com.example.estdelivery.domain.Account + +interface LoadAccountsPort { + fun loadAccounts(userId: Long): List + fun loadAccount(userId: Long, accountId: Long): Account +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/application/port/out/TransactionPersistencePort.kt b/src/main/kotlin/com/example/estdelivery/application/port/out/TransactionPersistencePort.kt new file mode 100644 index 0000000..b60081e --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/application/port/out/TransactionPersistencePort.kt @@ -0,0 +1,4 @@ +package com.example.estdelivery.application.port.out + +interface TransactionPersistencePort { +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/application/port/out/UserPersistencePort.kt b/src/main/kotlin/com/example/estdelivery/application/port/out/UserPersistencePort.kt new file mode 100644 index 0000000..a8f60d4 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/application/port/out/UserPersistencePort.kt @@ -0,0 +1,7 @@ +package com.example.estdelivery.application.port.out + +import com.example.estdelivery.domain.User + +interface UserPersistencePort { + fun save(user: User) +} \ No newline at end of file From 8f873d2b500effbb9897afea07888d619e77e9bd Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 10:02:58 +0900 Subject: [PATCH 04/12] =?UTF-8?q?feat:=20port=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20useCase=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ProcessTransactionService.kt | 57 +++++++++++++++++++ .../service/RegisterAccountService.kt | 21 +++++++ .../service/RegisterUserService.kt | 20 +++++++ 3 files changed, 98 insertions(+) create mode 100644 src/main/kotlin/com/example/estdelivery/application/service/ProcessTransactionService.kt create mode 100644 src/main/kotlin/com/example/estdelivery/application/service/RegisterAccountService.kt create mode 100644 src/main/kotlin/com/example/estdelivery/application/service/RegisterUserService.kt diff --git a/src/main/kotlin/com/example/estdelivery/application/service/ProcessTransactionService.kt b/src/main/kotlin/com/example/estdelivery/application/service/ProcessTransactionService.kt new file mode 100644 index 0000000..9e2e366 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/application/service/ProcessTransactionService.kt @@ -0,0 +1,57 @@ +package com.example.estdelivery.application.service + +import com.example.estdelivery.application.port.`in`.ProcessTransactionUseCase +import com.example.estdelivery.application.port.out.AccountPersistencePort +import com.example.estdelivery.application.port.out.LoadAccountsPort +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.math.BigDecimal +import java.util.concurrent.ConcurrentHashMap + +@Service +class ProcessTransactionService( + private val accountPersistencePort: AccountPersistencePort, +// private val transactionPersistencePort: TransactionPersistencePort, +// private val userPersistencePort: UserPersistencePort, + private val loadAccountPort : LoadAccountsPort +) : ProcessTransactionUseCase { + + private val processingTransactions = ConcurrentHashMap() + + /* + * 1. 보내는 사용자의 계좌 정보 조회 + * 2. 받는 사용자의 계좌 정보 조회 + * 3. 보내는 사용자의 계좌에서 출금 + * 4. 받는 사용자의 계좌에 입금 + */ + @Transactional + override fun process( + senderId: Long, + senderAccountId: Long, + receiverId: Long, + receiverAccountId: Long, + amount: BigDecimal + ): BigDecimal { + if (processingTransactions.putIfAbsent("${senderId}${receiverId}", true) != null) { + throw RuntimeException("Processing same transaction") + } + + try { + val senderAccount = loadAccountPort.loadAccount(senderId, senderAccountId) + val receiverAccount = loadAccountPort.loadAccount(receiverId, receiverAccountId) + + senderAccount.withdraw(amount) + receiverAccount.deposit(amount) + + accountPersistencePort.updateAccountBalance(senderAccount) + accountPersistencePort.updateAccountBalance(receiverAccount) + + // TODO : 트랜잭션 정보 저장 + + } finally { + processingTransactions.remove("${senderId}${receiverId}") + } + + return amount + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/application/service/RegisterAccountService.kt b/src/main/kotlin/com/example/estdelivery/application/service/RegisterAccountService.kt new file mode 100644 index 0000000..0bd9bda --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/application/service/RegisterAccountService.kt @@ -0,0 +1,21 @@ +package com.example.estdelivery.application.service + +import com.example.estdelivery.application.port.out.AccountPersistencePort +import com.example.estdelivery.application.port.`in`.RegisterAccountUseCase +import com.example.estdelivery.application.utils.AccountNumberGenerator +import com.example.estdelivery.domain.Account +import org.springframework.stereotype.Service +import java.math.BigDecimal + +@Service +class RegisterAccountService( + private val accountPersistencePort: AccountPersistencePort +) : RegisterAccountUseCase { + override fun registerAccount(userId: Long) { + val accountNumber = AccountNumberGenerator.generate() + val initialBalance = BigDecimal.ZERO + + val account = Account(userId, accountNumber, initialBalance) + accountPersistencePort.registerAccount(account) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/application/service/RegisterUserService.kt b/src/main/kotlin/com/example/estdelivery/application/service/RegisterUserService.kt new file mode 100644 index 0000000..9a366c7 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/application/service/RegisterUserService.kt @@ -0,0 +1,20 @@ +package com.example.estdelivery.application.service + +import com.example.estdelivery.application.port.`in`.RegisterUserUseCase +import com.example.estdelivery.application.port.out.UserPersistencePort +import com.example.estdelivery.domain.User +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.math.BigDecimal + +@Service +class RegisterUserService( + private val userPersistencePort: UserPersistencePort +) : RegisterUserUseCase { + + @Transactional + override fun registerUser(name: String) { + val user = User(name) + userPersistencePort.save(user) + } +} \ No newline at end of file From 7b6a38746d707c5e59db5d80bba1563961a9f5cf Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 10:03:20 +0900 Subject: [PATCH 05/12] =?UTF-8?q?feat:=20=EA=B3=84=EC=A2=8C=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20Generator=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/utils/AccountNumberGenerator.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/kotlin/com/example/estdelivery/application/utils/AccountNumberGenerator.kt diff --git a/src/main/kotlin/com/example/estdelivery/application/utils/AccountNumberGenerator.kt b/src/main/kotlin/com/example/estdelivery/application/utils/AccountNumberGenerator.kt new file mode 100644 index 0000000..d085263 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/application/utils/AccountNumberGenerator.kt @@ -0,0 +1,13 @@ +package com.example.estdelivery.application.utils + +import java.util.concurrent.atomic.AtomicLong + +object AccountNumberGenerator { + private const val ACCOUNT_NUMBER_LENGTH = 10 + private val lastNumber = AtomicLong(System.currentTimeMillis()) + + fun generate(): String { + val newNumber = lastNumber.incrementAndGet() + return newNumber.toString().takeLast(ACCOUNT_NUMBER_LENGTH) + } +} \ No newline at end of file From 184f868e1ed74813c46b03b0304fc890da68d45d Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 10:03:59 +0900 Subject: [PATCH 06/12] =?UTF-8?q?feat:=20user=20infrastructure=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/persistence/user/entity/UserEntity.kt | 26 +++++++++++++++++++ .../out/persistence/user/mapper/UserMapper.kt | 19 ++++++++++++++ .../user/repository/UserRepository.kt | 7 +++++ 3 files changed, 52 insertions(+) create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/entity/UserEntity.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/mapper/UserMapper.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/repository/UserRepository.kt diff --git a/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/entity/UserEntity.kt b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/entity/UserEntity.kt new file mode 100644 index 0000000..519c578 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/entity/UserEntity.kt @@ -0,0 +1,26 @@ +package com.example.estdelivery.adapter.out.persistence.user.entity + +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.Table +import java.math.BigDecimal + +@Entity +@Table(name = "user") +class UserEntity( + name: String +// balance: BigDecimal +) { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + var id: Long? = null + protected set + + var name: String? = name + protected set + +// var balance: BigDecimal = balance +// protected set +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/mapper/UserMapper.kt b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/mapper/UserMapper.kt new file mode 100644 index 0000000..82174b2 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/mapper/UserMapper.kt @@ -0,0 +1,19 @@ +package com.example.estdelivery.adapter.out.persistence.user.mapper + +import com.example.estdelivery.adapter.out.persistence.user.entity.UserEntity +import com.example.estdelivery.domain.User + +fun User.toEntity(): UserEntity { + return UserEntity( + name = this.name +// balance = this.balance + ) +} + +fun UserEntity.toDomain(): User { + return User( + id = this.id!!, + name = this.name!!, +// balance = this.balance + ) +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/repository/UserRepository.kt b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/repository/UserRepository.kt new file mode 100644 index 0000000..679e6c1 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/repository/UserRepository.kt @@ -0,0 +1,7 @@ +package com.example.estdelivery.adapter.out.persistence.user.repository + +import com.example.estdelivery.adapter.out.persistence.user.entity.UserEntity +import org.springframework.data.jpa.repository.JpaRepository + +interface UserRepository : JpaRepository { +} \ No newline at end of file From b6e236cf0ed37197ce866e68701d3f7611b7a7fe Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 10:04:29 +0900 Subject: [PATCH 07/12] =?UTF-8?q?feat:=20user=20=EC=99=B8=EB=B6=80=20?= =?UTF-8?q?=EC=96=B4=EB=8E=81=ED=84=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/adapter/UserPersistenceAdapter.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/adapter/UserPersistenceAdapter.kt diff --git a/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/adapter/UserPersistenceAdapter.kt b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/adapter/UserPersistenceAdapter.kt new file mode 100644 index 0000000..92ee016 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/user/adapter/UserPersistenceAdapter.kt @@ -0,0 +1,16 @@ +package com.example.estdelivery.adapter.out.persistence.user.adapter + +import com.example.estdelivery.adapter.out.persistence.user.repository.UserRepository +import com.example.estdelivery.adapter.out.persistence.user.mapper.toEntity +import com.example.estdelivery.application.port.out.UserPersistencePort +import com.example.estdelivery.domain.User +import org.springframework.stereotype.Component + +@Component +class UserPersistenceAdapter( + private val userRepository: UserRepository +) : UserPersistencePort { + override fun save(user: User) { + userRepository.save(user.toEntity()) + } +} \ No newline at end of file From e63e6cba1aad5491593a83b7785b8a1f84886e3b Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 10:04:50 +0900 Subject: [PATCH 08/12] =?UTF-8?q?feat:=20account=20infrastructure=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../account/entity/AccountEntity.kt | 34 +++++++++++++++++++ .../account/mapper/AccountMapper.kt | 21 ++++++++++++ .../account/repository/AccountRepository.kt | 8 +++++ 3 files changed, 63 insertions(+) create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/entity/AccountEntity.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/mapper/AccountMapper.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/repository/AccountRepository.kt diff --git a/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/entity/AccountEntity.kt b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/entity/AccountEntity.kt new file mode 100644 index 0000000..a0be0be --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/entity/AccountEntity.kt @@ -0,0 +1,34 @@ +package com.example.estdelivery.adapter.out.persistence.account.entity + +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.Table +import java.math.BigDecimal + +@Entity +@Table(name = "account") +class AccountEntity( + userId: Long, + accountNumber: String, + balance: BigDecimal +) { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + var id: Long? = null + protected set + + var userId: Long = userId + protected set + + var accountNumber: String = accountNumber + protected set + + var balance: BigDecimal = balance + protected set + + fun updateBalance(amount: BigDecimal) { + balance += amount + } +} diff --git a/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/mapper/AccountMapper.kt b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/mapper/AccountMapper.kt new file mode 100644 index 0000000..a3aefa0 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/mapper/AccountMapper.kt @@ -0,0 +1,21 @@ +package com.example.estdelivery.adapter.out.persistence.account.mapper + +import com.example.estdelivery.adapter.out.persistence.account.entity.AccountEntity +import com.example.estdelivery.domain.Account + +fun Account.toEntity(): AccountEntity { + return AccountEntity( + userId = this.userId, + accountNumber = this.accountNumber, + balance = this.balance + ) +} + +fun AccountEntity.toDomain(): Account { + return Account( + id = this.id!!, + userId = this.userId, + accountNumber = this.accountNumber, + balance = this.balance + ) +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/repository/AccountRepository.kt b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/repository/AccountRepository.kt new file mode 100644 index 0000000..07ece23 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/repository/AccountRepository.kt @@ -0,0 +1,8 @@ +package com.example.estdelivery.adapter.out.persistence.account.repository + +import com.example.estdelivery.adapter.out.persistence.account.entity.AccountEntity +import org.springframework.data.jpa.repository.JpaRepository + +interface AccountRepository : JpaRepository { + fun findByIdAndUserId(id: Long, userId: Long): AccountEntity +} \ No newline at end of file From 1a53e3a82791adabb33ff4872e862f777f4a721a Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 10:05:12 +0900 Subject: [PATCH 09/12] =?UTF-8?q?feat:=20account=20=EC=96=B4=EB=8E=81?= =?UTF-8?q?=ED=84=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/AccountPersistenceAdapter.kt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/adapter/AccountPersistenceAdapter.kt diff --git a/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/adapter/AccountPersistenceAdapter.kt b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/adapter/AccountPersistenceAdapter.kt new file mode 100644 index 0000000..cecc0e1 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/account/adapter/AccountPersistenceAdapter.kt @@ -0,0 +1,33 @@ +package com.example.estdelivery.adapter.out.persistence.account.adapter + +import com.example.estdelivery.adapter.out.persistence.account.mapper.toDomain +import com.example.estdelivery.adapter.out.persistence.account.mapper.toEntity +import com.example.estdelivery.adapter.out.persistence.account.repository.AccountRepository +import com.example.estdelivery.application.port.out.AccountPersistencePort +import com.example.estdelivery.application.port.out.LoadAccountsPort +import com.example.estdelivery.domain.Account +import org.springframework.stereotype.Component + +@Component +class AccountPersistenceAdapter( + private val accountRepository: AccountRepository +) : AccountPersistencePort, LoadAccountsPort { + override fun loadAccount(userId: Long, accountId: Long): Account { + return accountRepository.findByIdAndUserId(accountId, userId).toDomain() + } + + override fun loadAccounts(userId: Long): List { + TODO() + } + + override fun updateAccountBalance(account: Account) { + val accountEntity = accountRepository.findById(account.id!!).orElseThrow { + throw Exception("account not found") + } + accountEntity.updateBalance(account.balance) + } + + override fun registerAccount(account: Account) { + accountRepository.save(account.toEntity()) + } +} \ No newline at end of file From c77c0c3b87eb5bf92046f0a1904700e831a54d6a Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 10:05:29 +0900 Subject: [PATCH 10/12] =?UTF-8?q?feat:=20transactionEntity=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../transaction/entity/TransactionEntity.kt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/out/persistence/transaction/entity/TransactionEntity.kt diff --git a/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/transaction/entity/TransactionEntity.kt b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/transaction/entity/TransactionEntity.kt new file mode 100644 index 0000000..bc3ae89 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/out/persistence/transaction/entity/TransactionEntity.kt @@ -0,0 +1,27 @@ +package com.example.estdelivery.adapter.out.persistence.transaction.entity + +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.Table +import java.math.BigDecimal + +@Entity +@Table(name = "transaction") +class TransactionEntity( + accountId: String, + amount: BigDecimal +) { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + var id: Long? = null + protected set + + var accountId: String? = accountId + protected set + + var amount: BigDecimal = amount + protected set +} \ No newline at end of file From 8c014dc134d9156073ff2425be3b880911e47d83 Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 10:05:58 +0900 Subject: [PATCH 11/12] =?UTF-8?q?feat:=20web=20controller=20=EB=B0=8F=20dt?= =?UTF-8?q?o=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/in/web/AccountController.kt | 34 +++++++++++++++++++ .../in/web/ProcessTransactionController.kt | 27 +++++++++++++++ .../adapter/in/web/RegisterUserController.kt | 19 +++++++++++ .../account/request/RegisterAccountRequest.kt | 5 +++ .../account/response/AccountDetailResponse.kt | 6 ++++ .../response/AccountSummaryResponse.kt | 6 ++++ .../dto/transaction/request/DepositRequest.kt | 3 ++ .../dto/transaction/request/RemitRequest.kt | 12 +++++++ .../dto/user/request/RegisterUserRequest.kt | 5 +++ 9 files changed, 117 insertions(+) create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/in/web/AccountController.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/in/web/ProcessTransactionController.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/in/web/RegisterUserController.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/request/RegisterAccountRequest.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/response/AccountDetailResponse.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/response/AccountSummaryResponse.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/transaction/request/DepositRequest.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/transaction/request/RemitRequest.kt create mode 100644 src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/user/request/RegisterUserRequest.kt diff --git a/src/main/kotlin/com/example/estdelivery/adapter/in/web/AccountController.kt b/src/main/kotlin/com/example/estdelivery/adapter/in/web/AccountController.kt new file mode 100644 index 0000000..7a149ae --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/in/web/AccountController.kt @@ -0,0 +1,34 @@ +package com.example.estdelivery.adapter.`in`.web + +import com.example.estdelivery.adapter.`in`.web.dto.account.request.RegisterAccountRequest +import com.example.estdelivery.adapter.`in`.web.dto.account.response.AccountSummaryResponse +import com.example.estdelivery.application.port.`in`.RegisterAccountUseCase +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.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/accounts") +class AccountController( + private val registerAccountUseCase: RegisterAccountUseCase +) { + + @GetMapping + fun getAccounts(@RequestParam userId: Long): List { + TODO() + } + + @GetMapping("/{id}") + fun getAccount(@PathVariable id: Long): AccountSummaryResponse { + TODO() + } + + @PostMapping + fun registerAccount(@RequestBody request: RegisterAccountRequest) { + registerAccountUseCase.registerAccount(request.userId) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/adapter/in/web/ProcessTransactionController.kt b/src/main/kotlin/com/example/estdelivery/adapter/in/web/ProcessTransactionController.kt new file mode 100644 index 0000000..fa05574 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/in/web/ProcessTransactionController.kt @@ -0,0 +1,27 @@ +package com.example.estdelivery.adapter.`in`.web + +import com.example.estdelivery.adapter.`in`.web.dto.transaction.request.RemitRequest +import com.example.estdelivery.application.port.`in`.ProcessTransactionUseCase +import com.example.estdelivery.application.service.ProcessTransactionService +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 + +@RestController +@RequestMapping("/transactions") +class ProcessTransactionController( + private val processTransactionUseCase: ProcessTransactionUseCase +) { + + @PostMapping + fun processTransaction(@RequestBody request: RemitRequest) { + processTransactionUseCase.process( + request.senderId, + request.senderAccountId, + request.receiverId, + request.receiverAccountId, + request.amount + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/adapter/in/web/RegisterUserController.kt b/src/main/kotlin/com/example/estdelivery/adapter/in/web/RegisterUserController.kt new file mode 100644 index 0000000..6f64943 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/in/web/RegisterUserController.kt @@ -0,0 +1,19 @@ +package com.example.estdelivery.adapter.`in`.web + +import com.example.estdelivery.adapter.`in`.web.dto.user.request.RegisterUserRequest +import com.example.estdelivery.application.port.`in`.RegisterUserUseCase +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 + +@RestController +@RequestMapping("/users") +class RegisterUserController( + private val registerUserUseCase: RegisterUserUseCase +) { + @PostMapping + fun registerUser(@RequestBody request: RegisterUserRequest) { + registerUserUseCase.registerUser(request.name) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/request/RegisterAccountRequest.kt b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/request/RegisterAccountRequest.kt new file mode 100644 index 0000000..ca2e333 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/request/RegisterAccountRequest.kt @@ -0,0 +1,5 @@ +package com.example.estdelivery.adapter.`in`.web.dto.account.request + +data class RegisterAccountRequest( + val userId: Long +) diff --git a/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/response/AccountDetailResponse.kt b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/response/AccountDetailResponse.kt new file mode 100644 index 0000000..84cf09c --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/response/AccountDetailResponse.kt @@ -0,0 +1,6 @@ +package com.example.estdelivery.adapter.`in`.web.dto.account.response + +data class AccountDetailResponse( + val id: Long, + val balance: Long +) diff --git a/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/response/AccountSummaryResponse.kt b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/response/AccountSummaryResponse.kt new file mode 100644 index 0000000..d206040 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/account/response/AccountSummaryResponse.kt @@ -0,0 +1,6 @@ +package com.example.estdelivery.adapter.`in`.web.dto.account.response + +data class AccountSummaryResponse( + val id: Long, + val balance: Long +) diff --git a/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/transaction/request/DepositRequest.kt b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/transaction/request/DepositRequest.kt new file mode 100644 index 0000000..b7c8c24 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/transaction/request/DepositRequest.kt @@ -0,0 +1,3 @@ +//package com.example.estdelivery.adapter.`in`.web.dto.transaction.request +// +//data class DepositRequest() diff --git a/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/transaction/request/RemitRequest.kt b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/transaction/request/RemitRequest.kt new file mode 100644 index 0000000..d8f347b --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/transaction/request/RemitRequest.kt @@ -0,0 +1,12 @@ +package com.example.estdelivery.adapter.`in`.web.dto.transaction.request + +import java.math.BigDecimal +import java.time.LocalDateTime + +data class RemitRequest( + val senderId: Long, + val senderAccountId: Long, + val receiverId: Long, + val receiverAccountId: Long, + val amount: BigDecimal, +) diff --git a/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/user/request/RegisterUserRequest.kt b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/user/request/RegisterUserRequest.kt new file mode 100644 index 0000000..37dfda6 --- /dev/null +++ b/src/main/kotlin/com/example/estdelivery/adapter/in/web/dto/user/request/RegisterUserRequest.kt @@ -0,0 +1,5 @@ +package com.example.estdelivery.adapter.`in`.web.dto.user.request + +data class RegisterUserRequest( + val name: String, +) From c37ab4b954cb18dc2a611fce7e6245a203e22976 Mon Sep 17 00:00:00 2001 From: sksk713 Date: Mon, 19 Feb 2024 10:06:09 +0900 Subject: [PATCH 12/12] test: http api test --- http/AccountRequest.http | 7 +++++++ http/TransactionRequest.http | 11 +++++++++++ http/UserRequest.http | 7 +++++++ http/http-client.env.json | 5 +++++ 4 files changed, 30 insertions(+) create mode 100644 http/AccountRequest.http create mode 100644 http/TransactionRequest.http create mode 100644 http/UserRequest.http create mode 100644 http/http-client.env.json diff --git a/http/AccountRequest.http b/http/AccountRequest.http new file mode 100644 index 0000000..ce13b49 --- /dev/null +++ b/http/AccountRequest.http @@ -0,0 +1,7 @@ +### 계좌 등록 API +POST {{apiAddress}}/accounts +Content-Type: application/json + +{ + "userId": 1 +} \ No newline at end of file diff --git a/http/TransactionRequest.http b/http/TransactionRequest.http new file mode 100644 index 0000000..e236f2e --- /dev/null +++ b/http/TransactionRequest.http @@ -0,0 +1,11 @@ +### 사용자 추가 API +POST {{apiAddress}}/transactions +Content-Type: application/json + +{ + "senderId": 1, + "senderAccountId": 1, + "receiverId": 1, + "receiverAccountId": 2, + "amount": 1000 +} diff --git a/http/UserRequest.http b/http/UserRequest.http new file mode 100644 index 0000000..9f67991 --- /dev/null +++ b/http/UserRequest.http @@ -0,0 +1,7 @@ +### 사용자 추가 API +POST {{apiAddress}}/users +Content-Type: application/json + +{ + "name": "이상경" +} \ No newline at end of file diff --git a/http/http-client.env.json b/http/http-client.env.json new file mode 100644 index 0000000..765dfec --- /dev/null +++ b/http/http-client.env.json @@ -0,0 +1,5 @@ +{ + "local": { + "apiAddress": "http://localhost:8080" + } +}