refactor: organize backend by business responsibility
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import { Injectable, ServiceUnavailableException } from '@nestjs/common';
|
||||
import { isZero } from '../../../common/decimal';
|
||||
import {
|
||||
TbankAccessService,
|
||||
TbankClient,
|
||||
} from '../../../integrations/tbank/tbank.api';
|
||||
import { decimal } from '../../../integrations/tbank/decimal';
|
||||
import { totalsByCurrency } from '../portfolio/portfolio.api';
|
||||
import { BrokerageAccountDto } from './brokerage-account.dto';
|
||||
|
||||
@Injectable()
|
||||
export class BrokerageAccountsService {
|
||||
constructor(
|
||||
private readonly access: TbankAccessService,
|
||||
private readonly tbank: TbankClient,
|
||||
) {}
|
||||
|
||||
async list(userId: string): Promise<BrokerageAccountDto[]> {
|
||||
return this.access.withSupportedAccounts(
|
||||
userId,
|
||||
async ({ token, accounts }) =>
|
||||
Promise.all(
|
||||
accounts.map(async (account) => {
|
||||
const [portfolioResult, positionsResult] = await Promise.allSettled(
|
||||
[
|
||||
this.tbank.getPortfolio(token, account.id),
|
||||
this.tbank.getPositions(token, account.id),
|
||||
],
|
||||
);
|
||||
if (
|
||||
portfolioResult.status === 'rejected' &&
|
||||
!isTbankUnavailable(portfolioResult.reason)
|
||||
)
|
||||
throw portfolioResult.reason;
|
||||
if (
|
||||
positionsResult.status === 'rejected' &&
|
||||
!isTbankUnavailable(positionsResult.reason)
|
||||
)
|
||||
throw positionsResult.reason;
|
||||
if (
|
||||
portfolioResult.status === 'rejected' ||
|
||||
positionsResult.status === 'rejected'
|
||||
)
|
||||
return { ...account, portfolioSummary: null };
|
||||
const positions = portfolioResult.value.positions ?? [];
|
||||
let stockPositionCount = 0;
|
||||
let bondPositionCount = 0;
|
||||
for (const position of positions) {
|
||||
if (isZero(decimal(position.quantity ?? {}))) continue;
|
||||
const type = position.instrumentType?.toLowerCase();
|
||||
if (type === 'share') stockPositionCount += 1;
|
||||
if (type === 'bond') bondPositionCount += 1;
|
||||
}
|
||||
return {
|
||||
...account,
|
||||
portfolioSummary: {
|
||||
totalsByCurrency: totalsByCurrency(
|
||||
positions,
|
||||
positionsResult.value.money ?? [],
|
||||
),
|
||||
stockPositionCount,
|
||||
bondPositionCount,
|
||||
},
|
||||
};
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function isTbankUnavailable(error: unknown): boolean {
|
||||
if (!(error instanceof ServiceUnavailableException)) return false;
|
||||
const response = error.getResponse();
|
||||
return (
|
||||
typeof response === 'object' &&
|
||||
response !== null &&
|
||||
'code' in response &&
|
||||
response.code === 'TBANK_UNAVAILABLE'
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user