|
1 | 1 | import { Injectable, NotFoundException } from '@nestjs/common';
|
2 | 2 | import { ConfigService } from '@nestjs/config';
|
3 |
| -import { Observable, forkJoin, map } from 'rxjs'; |
| 3 | +import { Observable, forkJoin, map, of, switchMap } from 'rxjs'; |
| 4 | + |
| 5 | +import { Models } from '@o2s/framework/modules'; |
4 | 6 |
|
5 | 7 | import { AppHeaders } from '@o2s/api-harmonization/utils/headers';
|
6 | 8 |
|
@@ -32,18 +34,82 @@ export class OrderDetailsService {
|
32 | 34 | const order = this.orderService.getOrder({ ...params }, headers['authorization']);
|
33 | 35 |
|
34 | 36 | return forkJoin([cms, order]).pipe(
|
35 |
| - map(([cms, order]) => { |
| 37 | + switchMap(([cms, order]) => { |
36 | 38 | if (!order) {
|
37 | 39 | throw new NotFoundException();
|
38 | 40 | }
|
39 |
| - return mapOrderDetails( |
| 41 | + |
| 42 | + if (!order.items || order.items.length === 0) { |
| 43 | + return of({ cms, order }); |
| 44 | + } |
| 45 | + |
| 46 | + const productRequests = order.items.map((item) => { |
| 47 | + if (item.product?.id) { |
| 48 | + return of(item); |
| 49 | + } |
| 50 | + |
| 51 | + return this.productService |
| 52 | + .getProduct({ |
| 53 | + id: item.productId, |
| 54 | + locale: headers['x-locale'], |
| 55 | + }) |
| 56 | + .pipe( |
| 57 | + map((product) => ({ |
| 58 | + ...item, |
| 59 | + product, |
| 60 | + })), |
| 61 | + ); |
| 62 | + }); |
| 63 | + |
| 64 | + return forkJoin(productRequests).pipe( |
| 65 | + map((updatedItems) => { |
| 66 | + let filteredItems = updatedItems; |
| 67 | + const { offset = 0, limit = 5, sort = 'name_ASC' } = query; |
| 68 | + |
| 69 | + if (sort) { |
| 70 | + const [field, order] = sort.split('_'); |
| 71 | + const isAscending = order === 'ASC'; |
| 72 | + |
| 73 | + filteredItems = filteredItems.sort((a, b) => { |
| 74 | + const aValue = a[field as keyof Orders.Model.OrderItem]; |
| 75 | + const bValue = b[field as keyof Orders.Model.OrderItem]; |
| 76 | + |
| 77 | + if (field === 'discountTotal' || field === 'total' || field === 'price') { |
| 78 | + if (!aValue || !bValue) return 0; |
| 79 | + |
| 80 | + const aValueNumber = (aValue as Models.Price.Price).value; |
| 81 | + const bValueNumber = (bValue as Models.Price.Price).value; |
| 82 | + return isAscending ? aValueNumber - bValueNumber : bValueNumber - aValueNumber; |
| 83 | + } else if (field === 'name' || field === 'sku') { |
| 84 | + const aField = a.product?.[field] ?? ''; |
| 85 | + const bField = b.product?.[field] ?? ''; |
| 86 | + return isAscending ? aField.localeCompare(bField) : bField.localeCompare(aField); |
| 87 | + } else if (typeof aValue === 'string' && typeof bValue === 'string') { |
| 88 | + return isAscending ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue); |
| 89 | + } else if (typeof aValue === 'number' && typeof bValue === 'number') { |
| 90 | + return isAscending ? aValue - bValue : bValue - aValue; |
| 91 | + } |
| 92 | + return 0; |
| 93 | + }); |
| 94 | + } |
| 95 | + return { |
| 96 | + ...order, |
| 97 | + items: filteredItems.slice(Number(offset), Number(offset) + Number(limit)), |
| 98 | + totalItems: updatedItems.length, |
| 99 | + }; |
| 100 | + }), |
| 101 | + map((updatedOrder) => ({ cms, order: updatedOrder })), |
| 102 | + ); |
| 103 | + }), |
| 104 | + map(({ cms, order }) => |
| 105 | + mapOrderDetails( |
40 | 106 | cms,
|
41 |
| - order, |
| 107 | + order as Orders.Model.Order & { totalItems: number }, |
42 | 108 | headers['x-locale'],
|
43 | 109 | headers['x-client-timezone'] || '',
|
44 | 110 | this.defaultProductUnit,
|
45 |
| - ); |
46 |
| - }), |
| 111 | + ), |
| 112 | + ), |
47 | 113 | );
|
48 | 114 | }
|
49 | 115 | }
|
0 commit comments