From 12c722afe1a6efd01f21294ea6a010c2e9554e62 Mon Sep 17 00:00:00 2001 From: Anatoly Popov Date: Sun, 18 Aug 2024 11:02:21 +0300 Subject: [PATCH] Bugfix/Use currency conversion for fees and values (#3672) * Use currency conversion for fees and values * Update changelog --- CHANGELOG.md | 7 ++ apps/api/src/app/import/import.service.ts | 119 ++++++++++++---------- apps/api/src/app/order/order.service.ts | 54 +++++----- 3 files changed, 99 insertions(+), 81 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d16afe5f..f168e482 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Fixed + +- Fixed the currency conversion for fees and values in the dividend import by applying the correct rate based on the activity date +- Fixed the currency conversion for fees and values in the activities service by applying the correct rate based on the activity date + ## 2.104.1 - 2024-08-17 ### Fixed diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index 69e64387..30ab8706 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -82,60 +82,64 @@ export class ImportService { const Account = this.isUniqueAccount(accounts) ? accounts[0] : undefined; - return Object.entries(dividends).map(([dateString, { marketPrice }]) => { - const quantity = - historicalData.find((historicalDataItem) => { - return historicalDataItem.date === dateString; - })?.quantity ?? 0; + return await Promise.all( + Object.entries(dividends).map(async ([dateString, { marketPrice }]) => { + const quantity = + historicalData.find((historicalDataItem) => { + return historicalDataItem.date === dateString; + })?.quantity ?? 0; - const value = new Big(quantity).mul(marketPrice).toNumber(); + const value = new Big(quantity).mul(marketPrice).toNumber(); - const date = parseDate(dateString); - const isDuplicate = orders.some((activity) => { - return ( - activity.accountId === Account?.id && - activity.SymbolProfile.currency === assetProfile.currency && - activity.SymbolProfile.dataSource === assetProfile.dataSource && - isSameSecond(activity.date, date) && - activity.quantity === quantity && - activity.SymbolProfile.symbol === assetProfile.symbol && - activity.type === 'DIVIDEND' && - activity.unitPrice === marketPrice - ); - }); + const date = parseDate(dateString); + const isDuplicate = orders.some((activity) => { + return ( + activity.accountId === Account?.id && + activity.SymbolProfile.currency === assetProfile.currency && + activity.SymbolProfile.dataSource === assetProfile.dataSource && + isSameSecond(activity.date, date) && + activity.quantity === quantity && + activity.SymbolProfile.symbol === assetProfile.symbol && + activity.type === 'DIVIDEND' && + activity.unitPrice === marketPrice + ); + }); - const error: ActivityError = isDuplicate - ? { code: 'IS_DUPLICATE' } - : undefined; + const error: ActivityError = isDuplicate + ? { code: 'IS_DUPLICATE' } + : undefined; - return { - Account, - date, - error, - quantity, - value, - accountId: Account?.id, - accountUserId: undefined, - comment: undefined, - currency: undefined, - createdAt: undefined, - fee: 0, - feeInBaseCurrency: 0, - id: assetProfile.id, - isDraft: false, - SymbolProfile: assetProfile, - symbolProfileId: assetProfile.id, - type: 'DIVIDEND', - unitPrice: marketPrice, - updatedAt: undefined, - userId: Account?.userId, - valueInBaseCurrency: this.exchangeRateDataService.toCurrency( + return { + Account, + date, + error, + quantity, value, - assetProfile.currency, - userCurrency - ) - }; - }); + accountId: Account?.id, + accountUserId: undefined, + comment: undefined, + currency: undefined, + createdAt: undefined, + fee: 0, + feeInBaseCurrency: 0, + id: assetProfile.id, + isDraft: false, + SymbolProfile: assetProfile, + symbolProfileId: assetProfile.id, + type: 'DIVIDEND', + unitPrice: marketPrice, + updatedAt: undefined, + userId: Account?.userId, + valueInBaseCurrency: + await this.exchangeRateDataService.toCurrencyAtDate( + value, + assetProfile.currency, + userCurrency, + date + ) + }; + }) + ); } catch { return []; } @@ -432,18 +436,21 @@ export class ImportService { ...order, error, value, - feeInBaseCurrency: this.exchangeRateDataService.toCurrency( + feeInBaseCurrency: await this.exchangeRateDataService.toCurrencyAtDate( fee, assetProfile.currency, - userCurrency + userCurrency, + date ), // @ts-ignore SymbolProfile: assetProfile, - valueInBaseCurrency: this.exchangeRateDataService.toCurrency( - value, - assetProfile.currency, - userCurrency - ) + valueInBaseCurrency: + await this.exchangeRateDataService.toCurrencyAtDate( + value, + assetProfile.currency, + userCurrency, + date + ) }); } diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index 3b95211f..cb8543f9 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -483,34 +483,38 @@ export class OrderService { assetProfileIdentifiers ); - const activities = orders.map((order) => { - const assetProfile = assetProfiles.find(({ dataSource, symbol }) => { - return ( - dataSource === order.SymbolProfile.dataSource && - symbol === order.SymbolProfile.symbol - ); - }); + const activities = await Promise.all( + orders.map(async (order) => { + const assetProfile = assetProfiles.find(({ dataSource, symbol }) => { + return ( + dataSource === order.SymbolProfile.dataSource && + symbol === order.SymbolProfile.symbol + ); + }); - const value = new Big(order.quantity).mul(order.unitPrice).toNumber(); + const value = new Big(order.quantity).mul(order.unitPrice).toNumber(); - return { - ...order, - value, - // TODO: Use exchange rate of date - feeInBaseCurrency: this.exchangeRateDataService.toCurrency( - order.fee, - order.SymbolProfile.currency, - userCurrency - ), - SymbolProfile: assetProfile, - // TODO: Use exchange rate of date - valueInBaseCurrency: this.exchangeRateDataService.toCurrency( + return { + ...order, value, - order.SymbolProfile.currency, - userCurrency - ) - }; - }); + feeInBaseCurrency: + await this.exchangeRateDataService.toCurrencyAtDate( + order.fee, + order.SymbolProfile.currency, + userCurrency, + order.date + ), + SymbolProfile: assetProfile, + valueInBaseCurrency: + await this.exchangeRateDataService.toCurrencyAtDate( + value, + order.SymbolProfile.currency, + userCurrency, + order.date + ) + }; + }) + ); return { activities, count }; }