This commit is contained in:
@@ -0,0 +1,70 @@
|
|||||||
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
import { Cron } from '@nestjs/schedule';
|
||||||
|
import { CreateRequestContext } from '@mikro-orm/core';
|
||||||
|
import { EntityManager } from '@mikro-orm/postgresql';
|
||||||
|
import { OrderStatus } from '../../orders/interface/order.interface';
|
||||||
|
|
||||||
|
const COUNTED_ORDER_STATUSES = [
|
||||||
|
OrderStatus.PAID,
|
||||||
|
OrderStatus.PREPARING,
|
||||||
|
OrderStatus.DELIVERED_TO_WAITER,
|
||||||
|
OrderStatus.DELIVERED_TO_RECEPTIONIST,
|
||||||
|
OrderStatus.SHIPPED,
|
||||||
|
OrderStatus.COMPLETED,
|
||||||
|
];
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserRestaurantCrone {
|
||||||
|
private readonly logger = new Logger(UserRestaurantCrone.name);
|
||||||
|
|
||||||
|
constructor(private readonly em: EntityManager) {}
|
||||||
|
|
||||||
|
// run every day at 03:00 (3:00 AM)
|
||||||
|
@Cron('0 3 * * *', {
|
||||||
|
name: 'syncUserRestaurantOrderStats',
|
||||||
|
timeZone: 'UTC',
|
||||||
|
})
|
||||||
|
@CreateRequestContext()
|
||||||
|
async handleCron() {
|
||||||
|
try {
|
||||||
|
this.logger.debug('Starting nightly user-restaurant order stats sync');
|
||||||
|
|
||||||
|
const statusPlaceholders = COUNTED_ORDER_STATUSES.map(() => '?').join(', ');
|
||||||
|
|
||||||
|
await this.em.execute(
|
||||||
|
`UPDATE user_restuarant
|
||||||
|
SET order_count = 0, total_order_amount = 0, updated_at = now()
|
||||||
|
WHERE deleted_at IS NULL`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.em.execute(
|
||||||
|
`
|
||||||
|
UPDATE user_restuarant ur
|
||||||
|
SET
|
||||||
|
order_count = stats.order_count,
|
||||||
|
total_order_amount = stats.total_order_amount,
|
||||||
|
updated_at = now()
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
o.user_id,
|
||||||
|
o.restaurant_id,
|
||||||
|
COUNT(*)::int AS order_count,
|
||||||
|
COALESCE(SUM(o.total), 0)::int AS total_order_amount
|
||||||
|
FROM orders o
|
||||||
|
WHERE o.status IN (${statusPlaceholders})
|
||||||
|
AND o.deleted_at IS NULL
|
||||||
|
GROUP BY o.user_id, o.restaurant_id
|
||||||
|
) stats
|
||||||
|
WHERE ur.user_id = stats.user_id
|
||||||
|
AND ur.restaurant_id = stats.restaurant_id
|
||||||
|
AND ur.deleted_at IS NULL
|
||||||
|
`,
|
||||||
|
COUNTED_ORDER_STATUSES,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.logger.log('Successfully synced user-restaurant order stats');
|
||||||
|
} catch (err) {
|
||||||
|
this.logger.error(`UserRestaurantCrone failed: ${err?.message}`, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,11 +14,12 @@ import { PointTransaction } from './entities/point-transaction.entity';
|
|||||||
import { PointTransactionRepository } from './repositories/point-transaction.repository';
|
import { PointTransactionRepository } from './repositories/point-transaction.repository';
|
||||||
import { UserRestaurant } from './entities/user-restuarant.entity';
|
import { UserRestaurant } from './entities/user-restuarant.entity';
|
||||||
import { UserRestaurantRepository } from './repositories/user-restuarant.repository';
|
import { UserRestaurantRepository } from './repositories/user-restuarant.repository';
|
||||||
|
import { UserRestaurantCrone } from './crone/user-restuarant.crone';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [UserService, WalletService,
|
providers: [UserService, WalletService,
|
||||||
UserRepository, WalletTransactionRepository,
|
UserRepository, WalletTransactionRepository,
|
||||||
PointTransactionRepository, UserRestaurantRepository],
|
PointTransactionRepository, UserRestaurantRepository, UserRestaurantCrone],
|
||||||
controllers: [UsersController],
|
controllers: [UsersController],
|
||||||
imports: [
|
imports: [
|
||||||
MikroOrmModule.forFeature([User, UserAddress, WalletTransaction, PointTransaction, UserRestaurant]),
|
MikroOrmModule.forFeature([User, UserAddress, WalletTransaction, PointTransaction, UserRestaurant]),
|
||||||
|
|||||||
Reference in New Issue
Block a user