diff --git a/src/subdomains/core/custody/services/custody-order.service.ts b/src/subdomains/core/custody/services/custody-order.service.ts index 4d61a1a926..d27cb43aae 100644 --- a/src/subdomains/core/custody/services/custody-order.service.ts +++ b/src/subdomains/core/custody/services/custody-order.service.ts @@ -227,12 +227,27 @@ export class CustodyOrderService { } async getOrdersByUserData(userDataId: number): Promise { - const orders = await this.custodyOrderRepo.find({ - where: { user: { userData: { id: userDataId } }, status: Not(CustodyOrderStatus.CREATED) }, - relations: { inputAsset: true, outputAsset: true, transactionRequest: true }, - order: { created: 'DESC' }, - take: 100, - }); + const orders = await this.custodyOrderRepo + .createQueryBuilder('custodyOrder') + .leftJoinAndSelect('custodyOrder.inputAsset', 'inputAsset') + .leftJoinAndSelect('custodyOrder.outputAsset', 'outputAsset') + .leftJoinAndSelect('custodyOrder.transactionRequest', 'transactionRequest') + .innerJoin('custodyOrder.user', 'user') + .innerJoin('user.userData', 'userData') + .where('userData.id = :userDataId', { userDataId }) + .andWhere('custodyOrder.status != :createdStatus', { createdStatus: CustodyOrderStatus.CREATED }) + // The list shows completedAt where the order is completed, created otherwise. Sorting by + // created alone would put rows out of order against the dates the reader can see. + .orderBy('COALESCE("custodyOrder"."completedAt", "custodyOrder"."created")', 'DESC') + // Two orders can share a timestamp, and an undefined order among them would let rows swap + // places between calls - or cross the cap below and vanish. The id keeps it deterministic. + .addOrderBy('custodyOrder.id', 'DESC') + // limit, not take: take() splits the query in two and parses the raw orderBy at every dot, + // which turns the expression above into a lookup for an alias named COALESCE("custodyOrder" + // and throws on every call. Every relation joined here is to-one, so no row can be + // duplicated and limiting rows is the same as limiting entities. + .limit(100) + .getMany(); return CustodyOrderHistoryDtoMapper.mapList(orders); }