order report by date
This commit is contained in:
@@ -13,6 +13,7 @@ import { Permissions } from 'src/common/decorators/permissions.decorator';
|
|||||||
import { Permission } from 'src/common/enums/permission.enum';
|
import { Permission } from 'src/common/enums/permission.enum';
|
||||||
import { AdminCreateOrderDto } from '../dto/admin-create-order.dto';
|
import { AdminCreateOrderDto } from '../dto/admin-create-order.dto';
|
||||||
import { FoodOrderReportDto } from '../dto/food-order-report.dto';
|
import { FoodOrderReportDto } from '../dto/food-order-report.dto';
|
||||||
|
import { DailyOrderReportDto } from '../dto/daily-order-report.dto';
|
||||||
|
|
||||||
@ApiTags('orders')
|
@ApiTags('orders')
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@@ -136,4 +137,12 @@ export class OrdersController {
|
|||||||
getFoodOrderReport(@RestId() restId: string, @Query() dto: FoodOrderReportDto) {
|
getFoodOrderReport(@RestId() restId: string, @Query() dto: FoodOrderReportDto) {
|
||||||
return this.ordersService.getFoodOrderReport(restId, dto);
|
return this.ordersService.getFoodOrderReport(restId, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(AdminAuthGuard)
|
||||||
|
@Permissions(Permission.VIEW_REPORTS)
|
||||||
|
@ApiOperation({ summary: 'Get order report grouped by day' })
|
||||||
|
@Get('admin/orders/report/by-day')
|
||||||
|
getDailyOrderReport(@RestId() restId: string, @Query() dto: DailyOrderReportDto) {
|
||||||
|
return this.ordersService.getDailyOrderReport(restId, dto);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { IsOptional, IsDateString, IsEnum } from 'class-validator';
|
||||||
|
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export enum DailyOrderReportSortBy {
|
||||||
|
Date = 'date',
|
||||||
|
TotalAmount = 'totalAmount',
|
||||||
|
OrderCount = 'orderCount',
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DailyOrderReportDto {
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
format: 'date-time',
|
||||||
|
description: 'Filter orders from this date and time',
|
||||||
|
example: '2024-01-01T08:00:00.000Z',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsDateString()
|
||||||
|
from?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
format: 'date-time',
|
||||||
|
description: 'Filter orders until this date and time',
|
||||||
|
example: '2024-12-31T23:59:59.000Z',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsDateString()
|
||||||
|
to?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
enum: DailyOrderReportSortBy,
|
||||||
|
default: DailyOrderReportSortBy.Date,
|
||||||
|
description: 'Sort results by date, total amount, or order count',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsEnum(DailyOrderReportSortBy)
|
||||||
|
sortBy: DailyOrderReportSortBy = DailyOrderReportSortBy.Date;
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ import { OrderCreatedEvent, OrderStatusChangedEvent } from '../events/order.even
|
|||||||
import { OrderMessage } from 'src/common/enums/message.enum';
|
import { OrderMessage } from 'src/common/enums/message.enum';
|
||||||
import { AdminCreateOrderDto } from '../dto/admin-create-order.dto';
|
import { AdminCreateOrderDto } from '../dto/admin-create-order.dto';
|
||||||
import { FoodOrderReportDto, FoodOrderReportSortBy } from '../dto/food-order-report.dto';
|
import { FoodOrderReportDto, FoodOrderReportSortBy } from '../dto/food-order-report.dto';
|
||||||
|
import { DailyOrderReportDto, DailyOrderReportSortBy } from '../dto/daily-order-report.dto';
|
||||||
import { normalizePhone } from 'src/modules/utils/phone.util';
|
import { normalizePhone } from 'src/modules/utils/phone.util';
|
||||||
type OrderItemData = { food: Food; quantity: number; unitPrice: number; discount: number };
|
type OrderItemData = { food: Food; quantity: number; unitPrice: number; discount: number };
|
||||||
|
|
||||||
@@ -817,4 +818,49 @@ console.log(cart);
|
|||||||
totalPrice: Number(row.total_price || 0),
|
totalPrice: Number(row.total_price || 0),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getDailyOrderReport(restId: string, dto: DailyOrderReportDto) {
|
||||||
|
const { from, to, sortBy = DailyOrderReportSortBy.Date } = dto;
|
||||||
|
|
||||||
|
const params: unknown[] = [restId];
|
||||||
|
const dateFilters: string[] = [];
|
||||||
|
|
||||||
|
if (from) {
|
||||||
|
params.push(new Date(from));
|
||||||
|
dateFilters.push(`AND o.created_at >= ?`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (to) {
|
||||||
|
params.push(new Date(to));
|
||||||
|
dateFilters.push(`AND o.created_at <= ?`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderColumn = {
|
||||||
|
[DailyOrderReportSortBy.Date]: `DATE_TRUNC('day', CAST(o.created_at AS timestamp))`,
|
||||||
|
[DailyOrderReportSortBy.TotalAmount]: 'total_amount',
|
||||||
|
[DailyOrderReportSortBy.OrderCount]: 'order_count',
|
||||||
|
}[sortBy];
|
||||||
|
|
||||||
|
const result = await this.em.execute(
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
TO_CHAR(DATE_TRUNC('day', CAST(o.created_at AS timestamp)), 'YYYY-MM-DD') as "date",
|
||||||
|
COUNT(o.id)::int as order_count,
|
||||||
|
COALESCE(SUM(o.total), 0)::numeric as total_amount
|
||||||
|
FROM orders o
|
||||||
|
WHERE o.restaurant_id = ?
|
||||||
|
${dateFilters.join('\n ')}
|
||||||
|
AND o.status NOT IN ('pendingPayment', 'canceled')
|
||||||
|
GROUP BY DATE_TRUNC('day', CAST(o.created_at AS timestamp))
|
||||||
|
ORDER BY ${orderColumn} DESC
|
||||||
|
`,
|
||||||
|
params,
|
||||||
|
);
|
||||||
|
|
||||||
|
return result.map((row: Record<string, unknown>) => ({
|
||||||
|
date: row.date,
|
||||||
|
orderCount: Number(row.order_count || 0),
|
||||||
|
totalAmount: Number(row.total_amount || 0),
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user