From e04645aeb9b1ebd23997d0cccb97dd2ac01175bf Mon Sep 17 00:00:00 2001 From: Adam Borbas Date: Tue, 16 Sep 2025 14:09:16 +0200 Subject: [PATCH] Left out --- Sources/Grodt/Application/routes.swift | 1 + .../DTOs/DTOMappers/PortfolioDTOMapper.swift | 2 +- .../brokerages/BrokerageAccountController.swift | 17 ++++++++++++----- .../brokerages/DTO/BrokerageAccountDTO.swift | 1 + .../DTO/BrokerageAccountDTOMapper.swift | 4 ++-- .../DTO}/BrokerageAccountInfoDTO.swift | 2 ++ .../Endpoints/brokerages/DTO/BrokerageDTO.swift | 2 +- .../brokerages/DTO/BrokerageDTOMapper.swift | 2 +- .../transactions/TransactionDTOMapper.swift | 8 ++++++-- Tests/GrodtTests/TestConstant.swift | 2 +- 10 files changed, 28 insertions(+), 13 deletions(-) rename Sources/Grodt/Endpoints/{transactions => brokerages/DTO}/BrokerageAccountInfoDTO.swift (71%) diff --git a/Sources/Grodt/Application/routes.swift b/Sources/Grodt/Application/routes.swift index 3ee50c5..4be4ed4 100644 --- a/Sources/Grodt/Application/routes.swift +++ b/Sources/Grodt/Application/routes.swift @@ -101,6 +101,7 @@ func routes(_ app: Application) async throws { performanceRepository: brokerageAccountDailyPerformanceRepository, performanceDTOMapper: DatedPerformanceDTOMapper(), currencyMapper: currencyDTOMapper, + transactionDTOMapper: transactionDTOMapper, currencyRepository: currencyRepository)) } diff --git a/Sources/Grodt/DTOs/DTOMappers/PortfolioDTOMapper.swift b/Sources/Grodt/DTOs/DTOMappers/PortfolioDTOMapper.swift index 57bf42b..9264854 100644 --- a/Sources/Grodt/DTOs/DTOMappers/PortfolioDTOMapper.swift +++ b/Sources/Grodt/DTOs/DTOMappers/PortfolioDTOMapper.swift @@ -43,7 +43,7 @@ class PortfolioDTOMapper { guard portfolio.$historicalDailyPerformance.value != nil, let latest = portfolio.historicalDailyPerformance.max(by: { $0.date < $1.date }) else { - return PerformanceDTO(moneyIn: 0, moneyOut: 0, profit: 0, totalReturn: 0) + return PerformanceDTO.zero } let moneyIn = latest.moneyIn diff --git a/Sources/Grodt/Endpoints/brokerages/BrokerageAccountController.swift b/Sources/Grodt/Endpoints/brokerages/BrokerageAccountController.swift index eb0b2a5..0025c98 100644 --- a/Sources/Grodt/Endpoints/brokerages/BrokerageAccountController.swift +++ b/Sources/Grodt/Endpoints/brokerages/BrokerageAccountController.swift @@ -7,16 +7,19 @@ struct BrokerageAccountController: RouteCollection { private let currencyMapper: CurrencyDTOMapper private let performanceDTOMapper: DatedPerformanceDTOMapper private let currencyRepository: CurrencyRepository + private let transactionDTOMapper: TransactionDTOMapper init(brokerageAccountRepository: BrokerageAccountRepository, performanceRepository: PostgresBrokerageAccountDailyPerformanceRepository, performanceDTOMapper: DatedPerformanceDTOMapper, currencyMapper: CurrencyDTOMapper, + transactionDTOMapper: TransactionDTOMapper, currencyRepository: CurrencyRepository) { self.brokerageAccountRepository = brokerageAccountRepository self.performanceRepository = performanceRepository self.performanceDTOMapper = performanceDTOMapper self.currencyMapper = currencyMapper + self.transactionDTOMapper = transactionDTOMapper self.currencyRepository = currencyRepository } @@ -32,13 +35,13 @@ struct BrokerageAccountController: RouteCollection { } } - private func list(req: Request) async throws -> [BrokerageAccountDTO] { + private func list(req: Request) async throws -> [BrokerageAccountInfoDTO] { let userID = try req.requireUserID() let items = try await brokerageAccountRepository.all(for: userID) return try await items.asyncMap { model in let performance = try await brokerageAccountRepository.performance(for: model.requireID()) let brokerage = try await model.$brokerage.get(on: req.db) - return BrokerageAccountDTO( + return BrokerageAccountInfoDTO( id: try model.requireID(), brokerageId: try brokerage.requireID(), brokerageName: brokerage.name, @@ -76,20 +79,23 @@ struct BrokerageAccountController: RouteCollection { brokerageName: brokerage.name, displayName: model.displayName, baseCurrency: currencyMapper.currency(from: model.baseCurrency), - performance: PerformanceDTO.zero) + performance: PerformanceDTO.zero, + transacitons: []) } private func detail(req: Request) async throws -> BrokerageAccountDTO { let userID = try req.requireUserID() let model = try await requireAccount(req, userID: userID) let brokerage = try await model.$brokerage.get(on: req.db) + let transactions = try await model.$transactions.get(on: req.db) let performance = try await brokerageAccountRepository.performance(for: model.requireID()) - return BrokerageAccountDTO(id: try model.requireID(), + return try await BrokerageAccountDTO(id: try model.requireID(), brokerageId: try brokerage.requireID(), brokerageName: brokerage.name, displayName: model.displayName, baseCurrency: currencyMapper.currency(from: model.baseCurrency), - performance: performance) + performance: performance, + transacitons: transactions.asyncMap { try await transactionDTOMapper.transaction(from: $0) }) } private func update(req: Request) async throws -> HTTPStatus { @@ -131,3 +137,4 @@ struct BrokerageAccountController: RouteCollection { } extension BrokerageAccountDTO: Content { } +extension BrokerageAccountInfoDTO: Content { } diff --git a/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageAccountDTO.swift b/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageAccountDTO.swift index a3e5d4e..66a2e8b 100644 --- a/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageAccountDTO.swift +++ b/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageAccountDTO.swift @@ -7,4 +7,5 @@ struct BrokerageAccountDTO: Codable { let displayName: String let baseCurrency: CurrencyDTO let performance: PerformanceDTO + let transacitons: [TransactionDTO] } diff --git a/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageAccountDTOMapper.swift b/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageAccountDTOMapper.swift index ca621f8..1bf6284 100644 --- a/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageAccountDTOMapper.swift +++ b/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageAccountDTOMapper.swift @@ -13,11 +13,11 @@ struct BrokerageAccountDTOMapper { self.database = database } - func brokerageAccount(from brokerageAccount: BrokerageAccount) async throws -> BrokerageAccountDTO { + func brokerageAccountInfo(from brokerageAccount: BrokerageAccount) async throws -> BrokerageAccountInfoDTO { try await brokerageAccount.$brokerage.load(on: database) let performance = try await brokerageAccountRepository.performance(for: brokerageAccount.requireID()) - return try BrokerageAccountDTO(id: brokerageAccount.requireID(), + return try BrokerageAccountInfoDTO(id: brokerageAccount.requireID(), brokerageId: brokerageAccount.brokerage.requireID(), brokerageName: brokerageAccount.brokerage.name, displayName: brokerageAccount.displayName, diff --git a/Sources/Grodt/Endpoints/transactions/BrokerageAccountInfoDTO.swift b/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageAccountInfoDTO.swift similarity index 71% rename from Sources/Grodt/Endpoints/transactions/BrokerageAccountInfoDTO.swift rename to Sources/Grodt/Endpoints/brokerages/DTO/BrokerageAccountInfoDTO.swift index 5492afd..c8a02ee 100644 --- a/Sources/Grodt/Endpoints/transactions/BrokerageAccountInfoDTO.swift +++ b/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageAccountInfoDTO.swift @@ -5,4 +5,6 @@ struct BrokerageAccountInfoDTO: Codable, Equatable { let brokerageId: UUID let brokerageName: String let displayName: String + let baseCurrency: CurrencyDTO + let performance: PerformanceDTO } diff --git a/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageDTO.swift b/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageDTO.swift index 13e3997..2ea40d7 100644 --- a/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageDTO.swift +++ b/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageDTO.swift @@ -3,6 +3,6 @@ import Foundation struct BrokerageDTO: Codable { let id: UUID let name: String - let accounts: [BrokerageAccountDTO] + let accounts: [BrokerageAccountInfoDTO] let performance: PerformanceDTO } diff --git a/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageDTOMapper.swift b/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageDTOMapper.swift index be0adcc..7e362c8 100644 --- a/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageDTOMapper.swift +++ b/Sources/Grodt/Endpoints/brokerages/DTO/BrokerageDTOMapper.swift @@ -16,7 +16,7 @@ struct BrokerageDTOMapper { func brokerage(from brokerage: Brokerage) async throws -> BrokerageDTO { try await brokerage.$accounts.load(on: database) let accountDTOs = try await brokerage.accounts.asyncMap { - try await accountDTOMapper.brokerageAccount(from: $0) + try await accountDTOMapper.brokerageAccountInfo(from: $0) } let performance = try await brokerageRepository.performance(for: brokerage.requireID()) return try BrokerageDTO( diff --git a/Sources/Grodt/Endpoints/transactions/TransactionDTOMapper.swift b/Sources/Grodt/Endpoints/transactions/TransactionDTOMapper.swift index b331d7a..1e71ae3 100644 --- a/Sources/Grodt/Endpoints/transactions/TransactionDTOMapper.swift +++ b/Sources/Grodt/Endpoints/transactions/TransactionDTOMapper.swift @@ -18,10 +18,14 @@ class TransactionDTOMapper { brokerageAccount = BrokerageAccountInfoDTO(id: try brokerAcc.requireID(), brokerageId: try brokerage.requireID(), brokerageName: brokerAcc.brokerage.name, - displayName: brokerAcc.displayName) + displayName: brokerAcc.displayName, + baseCurrency: currencyDTOMapper.currency(from: brokerAcc.baseCurrency), + performance: PerformanceDTO.zero) } + let portfolio = try await transaction.$portfolio.get(on: database) + return TransactionDTO(id: transaction.id?.uuidString ?? "", - portfolioName: transaction.portfolio.name, + portfolioName: portfolio.name, purchaseDate: transaction.purchaseDate, ticker: transaction.ticker, currency: currencyDTOMapper.currency(from: transaction.currency), diff --git a/Tests/GrodtTests/TestConstant.swift b/Tests/GrodtTests/TestConstant.swift index 7aba2ea..14b0fa7 100644 --- a/Tests/GrodtTests/TestConstant.swift +++ b/Tests/GrodtTests/TestConstant.swift @@ -19,7 +19,7 @@ enum TestConstant { } enum PerformanceDTOs { - static let zero = PerformanceDTO(moneyIn: 0, moneyOut: 0, profit: 0, totalReturn: 0) + static let zero = PerformanceDTO.zero } enum Currencies {