This commit is contained in:
2026-07-08 20:12:17 +03:30
parent 9aa3c4f7c1
commit ee5bc314b5
3 changed files with 89 additions and 29 deletions
@@ -61,6 +61,13 @@ export class OrderController {
return this.orderService.findOrdersAsAdmin(adminId, dto);
}
@Get('admin/orders/tab-counts')
@UseGuards(AdminAuthGuard)
@ApiOperation({ summary: 'Get order tab counts for admin order list' })
getAdminOrderTabCounts(@Query() dto: FindOrdersDto, @AdminId() adminId: string) {
return this.orderService.getAdminOrderTabCounts(adminId, dto);
}
@Get('admin/orders/:id')
@UseGuards(AdminAuthGuard)
@Permissions(PermissionEnum.VIEW_ORDERS)
+67 -12
View File
@@ -30,6 +30,27 @@ import { OrderCreatedEvent } from '../events/order.events';
import { InvoiceConfirmStatusEnum } from 'src/modules/invoice/enum/invoice-confirm-status.enum';
import { ChattService } from 'src/modules/chat/providers/chat.service';
type AdminOrderTabCounts = {
inProgress: number;
finished: number;
canceled: number;
invoiced: number;
};
const IN_PROGRESS_STATUSES: OrderStatusEnum[] = [
OrderStatusEnum.CREATED,
OrderStatusEnum.DESIGN_INITIATED,
OrderStatusEnum.DESIGN_FINISHED,
OrderStatusEnum.DESIGN_REVISION,
OrderStatusEnum.READY_TO_PRINTING,
OrderStatusEnum.IN_PRINTING,
OrderStatusEnum.READY_FOR_DELIVERY,
OrderStatusEnum.DELIVERED,
OrderStatusEnum.AFTER_PRINT_COVER,
OrderStatusEnum.AFTER_PRINT_BOXING,
OrderStatusEnum.AFTER_PRINT_CARTONING,
];
@Injectable()
export class OrderService {
private readonly logger = new Logger(OrderService.name);
@@ -159,6 +180,49 @@ export class OrderService {
}
}
async getAdminOrderTabCounts(adminId: string, dto: FindOrdersDto): Promise<AdminOrderTabCounts> {
const permissions = await this.adminService.ownedPermissions(adminId, [
PermissionEnum.VIEW_ORDERS,
PermissionEnum.VIEW_ASSIGNED_ORDERS,
]);
const canViewAnyOrder = permissions.includes(PermissionEnum.VIEW_ORDERS);
const canViewAssignedOrder = permissions.includes(PermissionEnum.VIEW_ASSIGNED_ORDERS);
if (!canViewAnyOrder && !canViewAssignedOrder) {
throw new ForbiddenException("You don't have permission to view orders");
}
const baseFilter: FindOrdersDto = {
...dto,
designerId:
canViewAnyOrder
? dto.designerId
: adminId,
};
const [inProgress, finished, canceled, invoiced] = await Promise.all([
this.orderRepository.countByFilters({
...baseFilter,
statuses: IN_PROGRESS_STATUSES,
}),
this.orderRepository.countByFilters({
...baseFilter,
statuses: [OrderStatusEnum.FINISHED],
}),
this.orderRepository.countByFilters({
...baseFilter,
statuses: [OrderStatusEnum.CANCELED],
}),
this.orderRepository.countByFilters({
...baseFilter,
statuses: [OrderStatusEnum.INVOICED],
}),
]);
return { inProgress, finished, canceled, invoiced };
}
async getOrderAsUser(userId: string, orderId: string): Promise<Order> {
const order = await this.findOrderOrFail(orderId)
if (order.user.id !== userId) {
@@ -254,18 +318,9 @@ export class OrderService {
return order;
}
const inProgressStatuses = [
OrderStatusEnum.DESIGN_INITIATED,
OrderStatusEnum.DESIGN_FINISHED,
OrderStatusEnum.DESIGN_REVISION,
OrderStatusEnum.READY_TO_PRINTING,
OrderStatusEnum.IN_PRINTING,
OrderStatusEnum.READY_FOR_DELIVERY,
OrderStatusEnum.DELIVERED,
OrderStatusEnum.AFTER_PRINT_COVER,
OrderStatusEnum.AFTER_PRINT_BOXING,
OrderStatusEnum.AFTER_PRINT_CARTONING,
];
const inProgressStatuses: OrderStatusEnum[] = IN_PROGRESS_STATUSES.filter(
(status) => status !== OrderStatusEnum.CREATED,
);
const canChangeToCancelled =
toStatus === OrderStatusEnum.CANCELED &&
@@ -12,23 +12,8 @@ export class OrderRepository extends EntityRepository<Order> {
super(em, Order);
}
async findAllPaginated(opts: FindOrdersDto): Promise<PaginatedResult<Order>> {
const {
page = 1,
limit = 10,
statuses,
search,
orderBy = 'createdAt',
order = 'desc',
userId,
from,
to,
categoryId,
designerId,
} = opts;
const offset = (page - 1) * limit;
private buildWhere(opts: FindOrdersDto): FilterQuery<Order> {
const { statuses, search, userId, from, to, categoryId, designerId } = opts;
const where: FilterQuery<Order> = {};
// Filter by statuses
@@ -89,6 +74,14 @@ export class OrderRepository extends EntityRepository<Order> {
where.$or = searchConditions;
}
return where;
}
async findAllPaginated(opts: FindOrdersDto): Promise<PaginatedResult<Order>> {
const { page = 1, limit = 10, orderBy = 'createdAt', order = 'desc' } = opts;
const offset = (page - 1) * limit;
const where = this.buildWhere(opts);
// First, fetch orders without reviews
const [data, total] = await this.findAndCount(where, {
limit,
@@ -110,4 +103,9 @@ export class OrderRepository extends EntityRepository<Order> {
},
};
}
async countByFilters(opts: FindOrdersDto): Promise<number> {
const where = this.buildWhere(opts);
return this.count(where);
}
}