src/profile/summary.service.ts
Properties |
|
Methods |
|
| Async getDealerSummary | ||||||
getDealerSummary(userJwtPayload: UserJwtPayload)
|
||||||
|
Defined in src/profile/summary.service.ts:196
|
||||||
|
Parameters :
Returns :
unknown
|
| Async getInvestorSummary | ||||||
getInvestorSummary(userJwtPayload: UserJwtPayload)
|
||||||
|
Defined in src/profile/summary.service.ts:45
|
||||||
|
Parameters :
Returns :
unknown
|
| Private Readonly docuSignService |
Type : DocuSignService
|
Decorators :
@Inject(DocuSignService)
|
|
Defined in src/profile/summary.service.ts:37
|
| Private Readonly fundAdminService |
Type : FundAdminService
|
Decorators :
@Inject(FundAdminService)
|
|
Defined in src/profile/summary.service.ts:40
|
| Private Readonly orderBookService |
Type : OrderBookService
|
Decorators :
@Inject(OrderBookService)
|
|
Defined in src/profile/summary.service.ts:43
|
| Private Readonly userService |
Type : UserService
|
Decorators :
@Inject(UserService)
|
|
Defined in src/profile/summary.service.ts:34
|
import {
EndUserRoles,
IGeDealerIdQuery,
IGetDealerTxsQuery,
IOrder,
RequestStatus,
UserJwtPayload,
} from "src/common/interfaces";
import {
Inject,
Injectable,
ServiceUnavailableException,
} from "@nestjs/common";
import { UserService } from "src/user/user.service";
import { DocuSignService } from "src/docusign/docusign.service";
import { encodeBytes32String } from "ethers";
import { ApolloQueryResult } from "@apollo/client";
import {
apolloClient,
getCurrentDealerIdQuery,
getDealerTxsQuery,
getInvestorTxsByDealerIdQuery,
} from "src/common/provider";
import { IOrderRequestWithDocusignStatus } from "src/docusign/docusign.interface";
import { FundAdminService } from "src/user/fundAdmin.service";
import { UserWithOnChainFields } from "src/user/user.interface";
import { OrderBookService } from "src/orderbook/orderbook.service";
@Injectable()
export class SummaryService {
@Inject(UserService)
private readonly userService: UserService;
@Inject(DocuSignService)
private readonly docuSignService: DocuSignService;
@Inject(FundAdminService)
private readonly fundAdminService: FundAdminService;
@Inject(OrderBookService)
private readonly orderBookService: OrderBookService;
async getInvestorSummary(userJwtPayload: UserJwtPayload) {
const [investor] = await this.userService.findUsersByFilter(
{
email: userJwtPayload.email,
},
true,
);
const subscribedFundsByType: Record<string, number> = {};
investor.subscribedFunds.forEach((fund) => {
if (!subscribedFundsByType[fund.fundType]) {
subscribedFundsByType[fund.fundType] = 1;
} else {
subscribedFundsByType[fund.fundType]++;
}
});
const dealerSubgraph: ApolloQueryResult<IGeDealerIdQuery> =
await apolloClient.query({
query: getCurrentDealerIdQuery,
variables: {
investorId: encodeBytes32String(investor._id.toString()),
},
});
if (dealerSubgraph.error) {
throw new ServiceUnavailableException(dealerSubgraph.error);
}
const investorSubgraph: ApolloQueryResult<IGetDealerTxsQuery> =
await apolloClient.query({
query: getInvestorTxsByDealerIdQuery,
variables: {
dealerId: dealerSubgraph.data.investor.associatedDealer.id,
investorId: encodeBytes32String(investor._id.toString()),
},
});
const { awaitingTxs, pendingTxs } = investorSubgraph.data.dealer;
let orderFromTime, orderToTime;
if (awaitingTxs.length && pendingTxs.length) {
orderFromTime =
awaitingTxs[awaitingTxs.length - 1].lastTimeUpdated >
pendingTxs[pendingTxs.length - 1].lastTimeUpdated
? pendingTxs[pendingTxs.length - 1].lastTimeUpdated
: awaitingTxs[awaitingTxs.length - 1].lastTimeUpdated;
orderToTime =
awaitingTxs[0].lastTimeUpdated > pendingTxs[0].lastTimeUpdated
? awaitingTxs[0].lastTimeUpdated
: pendingTxs[0].lastTimeUpdated;
}
if (!awaitingTxs.length && pendingTxs.length) {
orderFromTime = pendingTxs[pendingTxs.length - 1].lastTimeUpdated;
orderToTime = pendingTxs[0].lastTimeUpdated;
}
if (awaitingTxs.length && !pendingTxs.length) {
orderFromTime = awaitingTxs[awaitingTxs.length - 1].lastTimeUpdated;
orderToTime = awaitingTxs[0].lastTimeUpdated;
}
const pendingTxsAfterDocusign: IOrder[] = [];
const awaitingTxsAfterDocusign: IOrder[] = [];
if (!orderFromTime || !orderToTime) {
return {
yourActions: [],
awaitingOthers: [],
profile: investor,
};
}
const ordersTimeFilter = {
orderFromTime: new Date(
(Number(orderFromTime) - 60 * 60) * 1000,
).toISOString(),
orderToTime: new Date(
(Number(orderToTime) + 60 * 60) * 1000,
).toISOString(),
};
const orderRequests =
!awaitingTxs.length && !pendingTxs.length
? []
: await this.docuSignService.getInvestorSubmittedDocuments({
receiverEmail: investor.email,
...ordersTimeFilter,
});
const orderRequestById: Record<string, IOrderRequestWithDocusignStatus> =
{};
orderRequests.forEach((orderRequest) => {
orderRequestById[orderRequest.orderId] = orderRequest;
});
pendingTxs.forEach((order) => {
if (
orderRequestById[order.id] &&
orderRequestById[order.id].status === "underReview" &&
orderRequestById[order.id].docuSignStatus === "completed"
) {
awaitingTxsAfterDocusign.push(order);
return;
}
if (
orderRequestById[order.id] &&
orderRequestById[order.id].status === "rejected"
) {
return;
}
pendingTxsAfterDocusign.push(order);
});
awaitingTxs.forEach((order) => {
if (!orderRequestById[order.id]) {
pendingTxsAfterDocusign.push(order);
return;
}
if (
orderRequestById[order.id].status === "accepted" &&
order.status !== "Locked" &&
order.type === "Redemption"
) {
pendingTxsAfterDocusign.push(order);
return;
}
if (
orderRequestById[order.id].status === "underReview" &&
orderRequestById[order.id].docuSignStatus !== "completed"
) {
pendingTxsAfterDocusign.push(order);
return;
}
if (orderRequestById[order.id].status === "rejected") {
return;
}
awaitingTxsAfterDocusign.push(order);
});
const [pendingOrders, awaitingOrders] = await Promise.all([
this.orderBookService.addFundNameToOrder({
orders: pendingTxsAfterDocusign,
orderRequests,
}),
this.orderBookService.addFundNameToOrder({
orders: awaitingTxsAfterDocusign,
orderRequests,
}),
]);
return {
yourActions: pendingOrders,
awaitingOthers: awaitingOrders,
profile: investor,
subscribedFundsByType,
};
}
async getDealerSummary(userJwtPayload: UserJwtPayload) {
const dealer = await this.userService.findUserByProperty(
{
email: userJwtPayload.email,
},
true,
);
const subscribedFundsByType: Record<string, number> = {};
dealer.subscribedFunds.forEach((fund) => {
if (!subscribedFundsByType[fund.fundType]) {
subscribedFundsByType[fund.fundType] = 1;
} else {
subscribedFundsByType[fund.fundType]++;
}
});
const dealerSubgraph: ApolloQueryResult<IGetDealerTxsQuery> =
await apolloClient.query({
query: getDealerTxsQuery,
variables: {
dealerId: encodeBytes32String(dealer._id.toString()),
},
});
const investorIds = [];
const investors = await this.userService.findUsersByFilter({
onboardByEmail: userJwtPayload.email,
});
const investorsByIdBytes32: Record<string, UserWithOnChainFields> = {};
investorIds.push(
...investors.map((investor) => {
investorsByIdBytes32[encodeBytes32String(investor._id.toString())] =
investor;
return investor._id.toString();
}),
);
const accessRequests = await this.fundAdminService.getRequestsByFundsId(
EndUserRoles.dealer,
dealer.subscribedFunds.map((fund) => fund._id.toString()),
investorIds,
{},
);
let approvedCount = 0;
let waitingForApproval = 0;
accessRequests.forEach((userAccessRequest) => {
if (
userAccessRequest.accessRequests[
userAccessRequest.accessRequests.length - 1
].status === RequestStatus.accepted
) {
approvedCount++;
}
if (
userAccessRequest.accessRequests[
userAccessRequest.accessRequests.length - 1
].status === RequestStatus.underReview
) {
waitingForApproval++;
}
});
const { awaitingTxs, pendingTxs } = dealerSubgraph.data.dealer;
let orderFromTime, orderToTime;
if (awaitingTxs.length && pendingTxs.length) {
orderFromTime =
awaitingTxs[awaitingTxs.length - 1].lastTimeUpdated >
pendingTxs[pendingTxs.length - 1].lastTimeUpdated
? pendingTxs[pendingTxs.length - 1].lastTimeUpdated
: awaitingTxs[awaitingTxs.length - 1].lastTimeUpdated;
orderToTime =
awaitingTxs[0].lastTimeUpdated > pendingTxs[0].lastTimeUpdated
? awaitingTxs[0].lastTimeUpdated
: pendingTxs[0].lastTimeUpdated;
}
if (!awaitingTxs.length && pendingTxs.length) {
orderFromTime = pendingTxs[pendingTxs.length - 1].lastTimeUpdated;
orderToTime = pendingTxs[0].lastTimeUpdated;
}
if (awaitingTxs.length && !pendingTxs.length) {
orderFromTime = awaitingTxs[awaitingTxs.length - 1].lastTimeUpdated;
orderToTime = awaitingTxs[0].lastTimeUpdated;
}
const pendingTxsAfterDocusign: IOrder[] = [];
const awaitingTxsAfterDocusign: IOrder[] = [];
if (!orderFromTime || !orderToTime) {
return {
yourActions: [],
awaitingOthers: [],
approvedCount,
waitingForApproval,
subscribedFundsByType,
};
}
const ordersTimeFilter = {
orderFromTime: new Date(
(Number(orderFromTime) - 60 * 60) * 1000,
).toISOString(),
orderToTime: new Date(
(Number(orderToTime) + 60 * 60) * 1000,
).toISOString(),
};
const orderRequests =
!awaitingTxs.length && !pendingTxs.length
? []
: await this.docuSignService.getDealerSubmittedDocuments({
customFieldName: "dealerEmail",
customFieldValue: userJwtPayload.email,
...ordersTimeFilter,
});
const orderRequestById: Record<string, IOrderRequestWithDocusignStatus> =
{};
orderRequests.forEach((orderRequest) => {
orderRequestById[orderRequest.orderId] = orderRequest;
});
pendingTxs.forEach((order) => {
if (
orderRequestById[order.id] &&
orderRequestById[order.id].status === "underReview" &&
orderRequestById[order.id].docuSignStatus === "completed"
) {
awaitingTxsAfterDocusign.push(order);
return;
}
if (
orderRequestById[order.id] &&
orderRequestById[order.id].status === "rejected"
) {
return;
}
pendingTxsAfterDocusign.push(order);
});
awaitingTxs.forEach((order) => {
if (!orderRequestById[order.id]) {
pendingTxsAfterDocusign.push(order);
return;
}
if (
orderRequestById[order.id].status === "accepted" &&
order.status !== "Locked" &&
order.type === "Redemption"
) {
pendingTxsAfterDocusign.push(order);
return;
}
if (
orderRequestById[order.id].status === "underReview" &&
orderRequestById[order.id].docuSignStatus !== "completed"
) {
pendingTxsAfterDocusign.push(order);
return;
}
if (orderRequestById[order.id].status === "rejected") {
return;
}
awaitingTxsAfterDocusign.push(order);
});
const [pendingOrders, awaitingOrders] = await Promise.all([
this.orderBookService.addFundNameToOrder({
orders: pendingTxsAfterDocusign,
orderRequests,
}),
this.orderBookService.addFundNameToOrder({
orders: awaitingTxsAfterDocusign,
orderRequests,
}),
]);
return {
yourActions: pendingOrders.map((order) => {
return {
...order,
onBehalf: {
...order.onBehalf,
...investorsByIdBytes32[order.onBehalf.id],
},
};
}),
awaitingOthers: awaitingOrders.map((order) => {
return {
...order,
onBehalf: {
...order.onBehalf,
...investorsByIdBytes32[order.onBehalf.id],
},
};
}),
approvedCount,
waitingForApproval,
subscribedFundsByType,
};
}
}