diff --git a/src/modules/foods/crone/food.crone.ts b/src/modules/foods/crone/food.crone.ts new file mode 100644 index 0000000..5749702 --- /dev/null +++ b/src/modules/foods/crone/food.crone.ts @@ -0,0 +1,45 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { Cron } from '@nestjs/schedule'; +import { EntityManager } from '@mikro-orm/postgresql'; +import { Inventory } from '../../inventory/entities/inventory.entity'; + +@Injectable() +export class FoodStockCrone { + private readonly logger = new Logger(FoodStockCrone.name); + + constructor(private readonly em: EntityManager) {} + + // run every day at 00:03 + @Cron('3 0 * * *', { + name: 'resetAvailableStock', + timeZone: 'UTC', + }) + async handleCron() { + try { + this.logger.debug('Starting daily inventory reset (availableStock = totalStock)'); + + const inventories = await this.em.find(Inventory, {}); + if (!inventories || inventories.length === 0) { + this.logger.debug('No inventory records found to reset'); + return; + } + + this.logger.log(`Resetting available stock for ${inventories.length} inventory records`); + + await this.em.transactional(async em => { + for (const inv of inventories) { + // reload inside transaction to avoid concurrency issues + const record = await em.findOne(Inventory, { id: inv.id }); + if (!record) continue; + record.availableStock = record.totalStock; + em.persist(record); + } + await em.flush(); + }); + + this.logger.log('Daily inventory reset completed'); + } catch (err) { + this.logger.error(`FoodStockCrone failed: ${err?.message}`, err); + } + } +} diff --git a/src/modules/foods/food.module.ts b/src/modules/foods/food.module.ts index ee9a16c..68b0569 100644 --- a/src/modules/foods/food.module.ts +++ b/src/modules/foods/food.module.ts @@ -1,5 +1,6 @@ import { Module } from '@nestjs/common'; import { FoodService } from './providers/food.service'; +import { FoodStockCrone } from './crone/food.crone'; import { FoodController } from './controllers/food.controller'; import { CategoryController } from './controllers/category.controller'; import { CategoryService } from './providers/category.service'; @@ -15,9 +16,15 @@ import { UtilsModule } from '../utils/utils.module'; import { Favorite } from './entities/favorite.entity'; @Module({ - imports: [MikroOrmModule.forFeature([Food, Category, Favorite]), RestaurantsModule, AuthModule, JwtModule, UtilsModule], + imports: [ + MikroOrmModule.forFeature([Food, Category, Favorite]), + RestaurantsModule, + AuthModule, + JwtModule, + UtilsModule, + ], controllers: [FoodController, CategoryController], - providers: [FoodService, CategoryService, FoodRepository, CategoryRepository], + providers: [FoodService, CategoryService, FoodRepository, CategoryRepository, FoodStockCrone], exports: [FoodRepository, CategoryRepository], }) -export class FoodModule { } +export class FoodModule {}