From ee03f16390285f30417a084fb0a4918b96862523 Mon Sep 17 00:00:00 2001 From: akbarsaputrait Date: Sun, 27 Oct 2024 12:03:40 +0700 Subject: [PATCH] Implement pay amount on complete order --- .../restaurant/order/detail.controller.ts | 162 +-------------- .../restaurant/order/order.controller.ts | 3 - .../restaurant/order/detail.controller.ts | 162 +-------------- src/database/entities/core/order.entity.ts | 6 + .../migrations/1730004495642-order-pay.ts | 15 ++ src/library/helpers/order.helper.ts | 193 ++++++++++++++++++ src/library/typeorm/datasource.typeorm.ts | 14 +- 7 files changed, 228 insertions(+), 327 deletions(-) create mode 100644 src/database/migrations/1730004495642-order-pay.ts create mode 100644 src/library/helpers/order.helper.ts diff --git a/src/app/owner/restaurant/order/detail.controller.ts b/src/app/owner/restaurant/order/detail.controller.ts index f847367..284b43d 100644 --- a/src/app/owner/restaurant/order/detail.controller.ts +++ b/src/app/owner/restaurant/order/detail.controller.ts @@ -4,182 +4,28 @@ import { OwnerAuthGuard } from '@core/guards/auth.guard'; import { OwnerGuard } from '@core/guards/owner.guard'; import { PdfService } from '@core/services/pdf.service'; import { PermAct, PermOwner } from '@core/services/role.service'; -import { Notification, NotificationType } from '@db/entities/core/notification.entity'; -import { OrderProduct, OrderProductStatus } from '@db/entities/core/order-product.entity'; import { Order, OrderStatus } from '@db/entities/core/order.entity'; import { Owner } from '@db/entities/owner/owner.entity'; -import { ProductStock } from '@db/entities/owner/product-stock.entity'; import { Restaurant } from '@db/entities/owner/restaurant.entity'; -import { Table, TableStatus } from '@db/entities/owner/table.entity'; import { OrderTransformer } from '@db/transformers/order.transformer'; import { GenericException } from '@lib/exceptions/generic.exception'; import { ValidationException } from '@lib/exceptions/validation.exception'; import { config } from '@lib/helpers/config.helper'; +import { OrderHelper } from '@lib/helpers/order.helper'; import { time } from '@lib/helpers/time.helper'; -import { titleCase, writeFile } from '@lib/helpers/utils.helper'; +import { writeFile } from '@lib/helpers/utils.helper'; import { Validator } from '@lib/helpers/validator.helper'; import Logger from '@lib/logger/logger.library'; import Socket, { PubSubEventType, PubSubPayloadType, PubSubStatus } from '@lib/pubsub/pubsub.lib'; import { Permissions } from '@lib/rbac'; -import AppDataSource from '@lib/typeorm/datasource.typeorm'; import { uuid } from '@lib/uid/uuid.library'; import { Body, Controller, Get, Param, Put, Res, UseGuards } from '@nestjs/common'; -import { In } from 'typeorm'; @Controller(':order_id') @UseGuards(OwnerAuthGuard()) export class DetailController { constructor(private pdf: PdfService) {} - static async action(order: Order, action: OrderStatus, actor: Owner) { - try { - // @TODO: How "REJECTED" flow works - const stocks: ProductStock[] = []; - switch (action) { - case OrderStatus.Confirmed: { - if (order.status !== OrderStatus.WaitingApproval) { - throw new GenericException(`Order ${order.number} can't be confirmed.`); - } - - order.status = action; - break; - } - case OrderStatus.Preparing: { - if (order.status !== OrderStatus.Confirmed) { - throw new GenericException(`Order ${order.number} can't be set to Preparing.`); - } - order.status = action; - break; - } - case OrderStatus.Served: { - if (order.status !== OrderStatus.Preparing) { - throw new GenericException(`Order ${order.number} can't be set to Served.`); - } - order.status = action; - break; - } - case OrderStatus.WaitingPayment: { - if (order.status !== OrderStatus.Served) { - throw new GenericException(`Order ${order.number} can't be set to Waiting Payment.`); - } - order.status = action; - break; - } - case OrderStatus.Completed: { - if (order.status !== OrderStatus.WaitingPayment) { - throw new GenericException(`Order ${order.number} can't be set to Completed.`); - } - order.status = action; - order.billed_at = time().toDate(); - - const orderProducts = await OrderProduct.findBy({ order_id: order.id }); - const productStocks = await ProductStock.findBy({ - variant_id: In(orderProducts.map((val) => val.product_variant_id)), - location_id: order.location_id, - }); - - for (const stock of productStocks) { - const orderProduct = orderProducts.find((val) => val.product_variant_id === stock.variant_id); - if (orderProduct) { - stock.onhand -= stock.allocated; // Decrease Onhand Stock - stock.allocated -= orderProduct.qty; // Decrease Allocated Stock - stock.sold += orderProduct.qty; - stock.actor = actor ? actor.logName : 'System'; - stock.last_action = `Completed Order: ${order.number}`; - stocks.push(stock); - } - } - - break; - } - case OrderStatus.Cancelled: { - if (order.status !== OrderStatus.WaitingApproval) { - throw new GenericException(`Order ${order.number} can't be cancelled.`); - } - // @TODO: Able to cancel/decline Product and Recalculate Gross Total - - order.status = action; - - const orderProducts = await OrderProduct.findBy({ order_id: order.id }); - const productStocks = await ProductStock.findBy({ - variant_id: In(orderProducts.map((val) => val.product_variant_id)), - location_id: order.location_id, - }); - - for (const stock of productStocks) { - const orderProduct = orderProducts.find((val) => val.product_variant_id === stock.variant_id); - if (orderProduct) { - stock.allocated -= orderProduct.qty; // Decrease Allocated Stock - stock.actor = actor ? actor.logName : 'System'; - stocks.push(stock); - } - } - - break; - } - } - - const notification = new Notification(); - notification.title = 'Order Updated'; - notification.content = JSON.stringify(order); - notification.actor = 'System'; - notification.location_id = order.location_id; - notification.restaurant_id = order.restaurant_id; - notification.type = NotificationType.OrderUpdate; - notification.order_id = order.id; - - await AppDataSource.transaction(async (manager) => { - if (!order.staff_id && !order.owner_id) { - order.owner_id = actor.id; - } - - await manager.getRepository(Order).save(order); - - const orderProductStatus = { - [OrderStatus.Cancelled]: OrderProductStatus.Cancelled, - [OrderStatus.Completed]: OrderProductStatus.Served, - [OrderStatus.Preparing]: OrderProductStatus.Preparing, - }; - - if (order.status in orderProductStatus) { - await manager - .getRepository(OrderProduct) - .update({ order_id: order.id }, { status: orderProductStatus[order.status] }); - } - - if ([OrderStatus.Completed, OrderStatus.Cancelled].includes(order.status)) { - const table = await manager.getRepository(Table).findOneBy({ id: order.table_id }); - if (!table) { - throw new Error(`Table not found with ID: ${order.table_id}`); - } - - if (table.status !== TableStatus.InUse) { - throw new Error(`Table ${table.number} is not In Use`); - } - - table.status = TableStatus.Available; - await manager.getRepository(Table).save(table); - } - - // Update Stock - for (const stock of stocks) { - stock.last_action = `${titleCase(order.status)} Order: ${order.number}`; - stock.actor = actor.logName; - await manager.getRepository(ProductStock).save(stock); - } - - await manager.getRepository(Notification).save(notification); - }); - - Socket.getInstance().notify(notification.order_id, { - request_id: uuid(), - data: notification, - }); - } catch (error) { - throw error; - } - } - @Get() @UseGuards(OwnerGuard) @Permissions(`${PermOwner.Order}@${PermAct.R}`) @@ -196,6 +42,8 @@ export class DetailController { action: `required|in:${Object.values(OrderStatus) .filter((val) => val !== 'waiting_approval') .join(',')}`, + pay_amount: 'numeric|min:0', + change_amount: 'numeric|min:0', }; const validation = Validator.init(body, rules); if (validation.fails()) { @@ -203,7 +51,7 @@ export class DetailController { } const order = await Order.findOneByOrFail({ id: param.order_id }); - await DetailController.action(order, body.action, me); + await OrderHelper.processOrder(order, body.action, me, body); await order.reload(); return response.item(order, OrderTransformer); diff --git a/src/app/owner/restaurant/order/order.controller.ts b/src/app/owner/restaurant/order/order.controller.ts index 16131a5..62220b2 100644 --- a/src/app/owner/restaurant/order/order.controller.ts +++ b/src/app/owner/restaurant/order/order.controller.ts @@ -4,7 +4,6 @@ import { Rest } from '@core/decorators/restaurant.decorator'; import { Me } from '@core/decorators/user.decorator'; import { OwnerAuthGuard } from '@core/guards/auth.guard'; import { OwnerGuard } from '@core/guards/owner.guard'; -import { PdfService } from '@core/services/pdf.service'; import { PermAct, PermOwner } from '@core/services/role.service'; import { Order } from '@db/entities/core/order.entity'; import { Location } from '@db/entities/owner/location.entity'; @@ -26,8 +25,6 @@ import * as ExcelJS from 'exceljs'; @Controller() @UseGuards(OwnerAuthGuard()) export class OrderController { - constructor(private pdf: PdfService) {} - @Get() @UseGuards(OwnerGuard) @Permissions(`${PermOwner.Order}@${PermAct.R}`) diff --git a/src/app/staff/restaurant/order/detail.controller.ts b/src/app/staff/restaurant/order/detail.controller.ts index 53cbaba..b3783e9 100644 --- a/src/app/staff/restaurant/order/detail.controller.ts +++ b/src/app/staff/restaurant/order/detail.controller.ts @@ -4,182 +4,28 @@ import { StaffAuthGuard } from '@core/guards/auth.guard'; import { StaffGuard } from '@core/guards/staff.guard'; import { PdfService } from '@core/services/pdf.service'; import { PermAct, PermStaff } from '@core/services/role.service'; -import { Notification, NotificationType } from '@db/entities/core/notification.entity'; -import { OrderProduct, OrderProductStatus } from '@db/entities/core/order-product.entity'; import { Order, OrderStatus } from '@db/entities/core/order.entity'; -import { ProductStock } from '@db/entities/owner/product-stock.entity'; import { Restaurant } from '@db/entities/owner/restaurant.entity'; -import { Table, TableStatus } from '@db/entities/owner/table.entity'; import { StaffUser } from '@db/entities/staff/user.entity'; import { OrderTransformer } from '@db/transformers/order.transformer'; import { GenericException } from '@lib/exceptions/generic.exception'; import { ValidationException } from '@lib/exceptions/validation.exception'; import { config } from '@lib/helpers/config.helper'; +import { OrderHelper } from '@lib/helpers/order.helper'; import { time } from '@lib/helpers/time.helper'; -import { titleCase, writeFile } from '@lib/helpers/utils.helper'; +import { writeFile } from '@lib/helpers/utils.helper'; import { Validator } from '@lib/helpers/validator.helper'; import Logger from '@lib/logger/logger.library'; import Socket, { PubSubEventType, PubSubPayloadType, PubSubStatus } from '@lib/pubsub/pubsub.lib'; import { Permissions } from '@lib/rbac'; -import AppDataSource from '@lib/typeorm/datasource.typeorm'; import { uuid } from '@lib/uid/uuid.library'; import { Body, Controller, Get, Param, Put, Res, UseGuards } from '@nestjs/common'; -import { In } from 'typeorm'; @Controller(':order_id') @UseGuards(StaffAuthGuard()) export class DetailController { constructor(private pdf: PdfService) {} - static async action(order: Order, action: OrderStatus, actor: StaffUser) { - try { - // @TODO: How "REJECTED" flow works - const stocks: ProductStock[] = []; - switch (action) { - case OrderStatus.Confirmed: { - if (order.status !== OrderStatus.WaitingApproval) { - throw new GenericException(`Order ${order.number} can't be confirmed.`); - } - - order.status = action; - break; - } - case OrderStatus.Preparing: { - if (order.status !== OrderStatus.Confirmed) { - throw new GenericException(`Order ${order.number} can't be set to Preparing.`); - } - order.status = action; - break; - } - case OrderStatus.Served: { - if (order.status !== OrderStatus.Preparing) { - throw new GenericException(`Order ${order.number} can't be set to Served.`); - } - order.status = action; - break; - } - case OrderStatus.WaitingPayment: { - if (order.status !== OrderStatus.Served) { - throw new GenericException(`Order ${order.number} can't be set to Waiting Payment.`); - } - order.status = action; - break; - } - case OrderStatus.Completed: { - if (order.status !== OrderStatus.WaitingPayment) { - throw new GenericException(`Order ${order.number} can't be set to Completed.`); - } - order.status = action; - order.billed_at = time().toDate(); - - const orderProducts = await OrderProduct.findBy({ order_id: order.id }); - const productStocks = await ProductStock.findBy({ - variant_id: In(orderProducts.map((val) => val.product_variant_id)), - location_id: order.location_id, - }); - - for (const stock of productStocks) { - const orderProduct = orderProducts.find((val) => val.product_variant_id === stock.variant_id); - if (orderProduct) { - stock.onhand -= stock.allocated; // Decrease Onhand Stock - stock.allocated -= orderProduct.qty; // Decrease Allocated Stock - stock.sold += orderProduct.qty; - stock.actor = actor ? actor.logName : 'System'; - stock.last_action = `Completed Order: ${order.number}`; - stocks.push(stock); - } - } - - break; - } - case OrderStatus.Cancelled: { - if (order.status !== OrderStatus.WaitingApproval) { - throw new GenericException(`Order ${order.number} can't be cancelled.`); - } - // @TODO: Able to cancel/decline Product and Recalculate Gross Total - - order.status = action; - - const orderProducts = await OrderProduct.findBy({ order_id: order.id }); - const productStocks = await ProductStock.findBy({ - variant_id: In(orderProducts.map((val) => val.product_variant_id)), - location_id: order.location_id, - }); - - for (const stock of productStocks) { - const orderProduct = orderProducts.find((val) => val.product_variant_id === stock.variant_id); - if (orderProduct) { - stock.allocated -= orderProduct.qty; // Decrease Allocated Stock - stock.actor = actor ? actor.logName : 'System'; - stocks.push(stock); - } - } - - break; - } - } - - const notification = new Notification(); - notification.title = 'Order Updated'; - notification.content = JSON.stringify(order); - notification.actor = 'System'; - notification.location_id = order.location_id; - notification.restaurant_id = order.restaurant_id; - notification.type = NotificationType.OrderUpdate; - notification.order_id = order.id; - - await AppDataSource.transaction(async (manager) => { - if (!order.staff_id && !order.owner_id) { - order.staff_id = actor.id; - } - - await manager.getRepository(Order).save(order); - - const orderProductStatus = { - [OrderStatus.Cancelled]: OrderProductStatus.Cancelled, - [OrderStatus.Completed]: OrderProductStatus.Served, - [OrderStatus.Preparing]: OrderProductStatus.Preparing, - }; - - if (order.status in orderProductStatus) { - await manager - .getRepository(OrderProduct) - .update({ order_id: order.id }, { status: orderProductStatus[order.status] }); - } - - if ([OrderStatus.Completed, OrderStatus.Cancelled].includes(order.status)) { - const table = await manager.getRepository(Table).findOneBy({ id: order.table_id }); - if (!table) { - throw new Error(`Table not found with ID: ${order.table_id}`); - } - - if (table.status !== TableStatus.InUse) { - throw new Error(`Table ${table.number} is not In Use`); - } - - table.status = TableStatus.Available; - await manager.getRepository(Table).save(table); - } - - // Update Stock - for (const stock of stocks) { - stock.last_action = `${titleCase(order.status)} Order: ${order.number}`; - stock.actor = actor.logName; - await manager.getRepository(ProductStock).save(stock); - } - - await manager.getRepository(Notification).save(notification); - }); - - Socket.getInstance().notify(notification.order_id, { - request_id: uuid(), - data: notification, - }); - } catch (error) { - throw error; - } - } - @Get() @UseGuards(StaffGuard) @Permissions(`${PermStaff.Order}@${PermAct.R}`) @@ -196,6 +42,8 @@ export class DetailController { action: `required|in:${Object.values(OrderStatus) .filter((val) => val !== 'waiting_approval') .join(',')}`, + pay_amount: 'numeric|min:0', + change_amount: 'numeric|min:0', }; const validation = Validator.init(body, rules); if (validation.fails()) { @@ -203,7 +51,7 @@ export class DetailController { } const order = await Order.findOneByOrFail({ id: param.order_id }); - await DetailController.action(order, body.action, me); + await OrderHelper.processOrder(order, body.action, me, body); await order.reload(); return response.item(order, OrderTransformer); diff --git a/src/database/entities/core/order.entity.ts b/src/database/entities/core/order.entity.ts index 89edeec..767bfe6 100644 --- a/src/database/entities/core/order.entity.ts +++ b/src/database/entities/core/order.entity.ts @@ -50,6 +50,12 @@ export class Order extends BaseEntity { @PriceColumn() net_total: number; + @PriceColumn() + pay_amount: number; + + @PriceColumn() + change_amount: number; + @DateTimeColumn() billed_at: Date; diff --git a/src/database/migrations/1730004495642-order-pay.ts b/src/database/migrations/1730004495642-order-pay.ts new file mode 100644 index 0000000..bc45263 --- /dev/null +++ b/src/database/migrations/1730004495642-order-pay.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class OrderPay1730004495642 implements MigrationInterface { + name = 'OrderPay1730004495642'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`order\` ADD \`pay_amount\` decimal(16,2) NULL DEFAULT '0.00'`); + await queryRunner.query(`ALTER TABLE \`order\` ADD \`change_amount\` decimal(16,2) NULL DEFAULT '0.00'`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`order\` DROP COLUMN \`change_amount\``); + await queryRunner.query(`ALTER TABLE \`order\` DROP COLUMN \`pay_amount\``); + } +} diff --git a/src/library/helpers/order.helper.ts b/src/library/helpers/order.helper.ts new file mode 100644 index 0000000..3fe6942 --- /dev/null +++ b/src/library/helpers/order.helper.ts @@ -0,0 +1,193 @@ +import { Notification, NotificationType } from '@db/entities/core/notification.entity'; +import { OrderProduct, OrderProductStatus } from '@db/entities/core/order-product.entity'; +import { Order, OrderStatus } from '@db/entities/core/order.entity'; +import { Owner } from '@db/entities/owner/owner.entity'; +import { ProductStock } from '@db/entities/owner/product-stock.entity'; +import { Table, TableStatus } from '@db/entities/owner/table.entity'; +import { StaffUser } from '@db/entities/staff/user.entity'; +import { GenericException } from '@lib/exceptions/generic.exception'; +import Socket from '@lib/pubsub/pubsub.lib'; +import AppDataSource from '@lib/typeorm/datasource.typeorm'; +import { uuid } from '@lib/uid/uuid.library'; +import { has } from 'lodash'; +import { In } from 'typeorm'; +import { time } from './time.helper'; +import { titleCase } from './utils.helper'; + +export class OrderHelper { + static async processOrder( + order: Order, + action: OrderStatus, + actor: Owner | StaffUser, + body?: { pay_amount: number } | null + ): Promise { + try { + // @TODO: How "REJECTED" flow works + const stocks: ProductStock[] = []; + switch (action) { + case OrderStatus.Confirmed: { + if (order.status !== OrderStatus.WaitingApproval) { + throw new GenericException(`Order ${order.number} can't be confirmed.`); + } + + order.status = action; + break; + } + case OrderStatus.Preparing: { + if (order.status !== OrderStatus.Confirmed) { + throw new GenericException(`Order ${order.number} can't be set to Preparing.`); + } + order.status = action; + break; + } + case OrderStatus.Served: { + if (order.status !== OrderStatus.Preparing) { + throw new GenericException(`Order ${order.number} can't be set to Served.`); + } + order.status = action; + break; + } + case OrderStatus.WaitingPayment: { + if (order.status !== OrderStatus.Served) { + throw new GenericException(`Order ${order.number} can't be set to Waiting Payment.`); + } + order.status = action; + break; + } + case OrderStatus.Completed: { + if (order.status !== OrderStatus.WaitingPayment) { + throw new GenericException(`Order ${order.number} can't be set to Completed.`); + } + + if (body && !has(body, 'pay_amount')) { + throw new GenericException('Required pay amount'); + } + + const payAmount = Number(body.pay_amount); + + if (payAmount < order.gross_total) { + throw new GenericException(`Pay amount can't be less then Order total price`); + } + + if (payAmount >= order.gross_total) { + order.pay_amount = payAmount; + order.change_amount = Math.max(0, payAmount - order.gross_total); + } + + order.status = action; + order.billed_at = time().toDate(); + + const orderProducts = await OrderProduct.findBy({ order_id: order.id }); + const productStocks = await ProductStock.findBy({ + variant_id: In(orderProducts.map((val) => val.product_variant_id)), + location_id: order.location_id, + }); + + for (const stock of productStocks) { + const orderProduct = orderProducts.find((val) => val.product_variant_id === stock.variant_id); + if (orderProduct) { + stock.onhand -= stock.allocated; // Decrease Onhand Stock + stock.allocated -= orderProduct.qty; // Decrease Allocated Stock + stock.sold += orderProduct.qty; + stock.actor = actor ? actor.logName : 'System'; + stock.last_action = `Completed Order: ${order.number}`; + stocks.push(stock); + } + } + + break; + } + case OrderStatus.Cancelled: { + if (order.status !== OrderStatus.WaitingApproval) { + throw new GenericException(`Order ${order.number} can't be cancelled.`); + } + // @TODO: Able to cancel/decline Product and Recalculate Gross Total + + order.status = action; + + const orderProducts = await OrderProduct.findBy({ order_id: order.id }); + const productStocks = await ProductStock.findBy({ + variant_id: In(orderProducts.map((val) => val.product_variant_id)), + location_id: order.location_id, + }); + + for (const stock of productStocks) { + const orderProduct = orderProducts.find((val) => val.product_variant_id === stock.variant_id); + if (orderProduct) { + stock.allocated -= orderProduct.qty; // Decrease Allocated Stock + stock.actor = actor ? actor.logName : 'System'; + stocks.push(stock); + } + } + + break; + } + } + + const notification = new Notification(); + notification.title = 'Order Updated'; + notification.content = JSON.stringify(order); + notification.actor = 'System'; + notification.location_id = order.location_id; + notification.restaurant_id = order.restaurant_id; + notification.type = NotificationType.OrderUpdate; + notification.order_id = order.id; + + await AppDataSource.transaction(async (manager) => { + if (!order.staff_id && !order.owner_id) { + if (actor instanceof Owner) { + order.owner_id = actor.id; + } else if (actor instanceof StaffUser) { + order.staff_id = actor.id; + } + } + + await manager.getRepository(Order).save(order); + + const orderProductStatus = { + [OrderStatus.Cancelled]: OrderProductStatus.Cancelled, + [OrderStatus.Completed]: OrderProductStatus.Served, + [OrderStatus.Preparing]: OrderProductStatus.Preparing, + }; + + if (order.status in orderProductStatus) { + await manager + .getRepository(OrderProduct) + .update({ order_id: order.id }, { status: orderProductStatus[order.status] }); + } + + if ([OrderStatus.Completed, OrderStatus.Cancelled].includes(order.status)) { + const table = await manager.getRepository(Table).findOneBy({ id: order.table_id }); + if (!table) { + throw new Error(`Table not found with ID: ${order.table_id}`); + } + + if (table.status !== TableStatus.InUse) { + throw new Error(`Table ${table.number} is not In Use`); + } + + table.status = TableStatus.Available; + await manager.getRepository(Table).save(table); + } + + // Update Stock + for (const stock of stocks) { + stock.last_action = `${titleCase(order.status)} Order: ${order.number}`; + stock.actor = actor.logName; + await manager.getRepository(ProductStock).save(stock); + } + + await manager.getRepository(Notification).save(notification); + }); + + Socket.getInstance().notify(notification.order_id, { + request_id: uuid(), + data: notification, + }); + + return order; + } catch (error) { + throw error; + } + } +} diff --git a/src/library/typeorm/datasource.typeorm.ts b/src/library/typeorm/datasource.typeorm.ts index 2fee7cb..c451e0f 100644 --- a/src/library/typeorm/datasource.typeorm.ts +++ b/src/library/typeorm/datasource.typeorm.ts @@ -9,6 +9,7 @@ export class Datasource { if (Datasource._instance) { throw new Error('Error: Instantiation failed: Use Datasource.getInstance() instead of new'); } + this.initialize().catch(console.error); } public static getInstance(): Datasource { @@ -20,17 +21,10 @@ export class Datasource { } async initialize() { - if (!this._dataSource || !this._dataSource.isInitialized) { - this._dataSource = new DataTypeORM(database as any); + this._dataSource = new DataTypeORM(database as any); + if (!this._dataSource.isInitialized) { await this._dataSource.initialize(); - } - return this._dataSource; - } - - async destroy() { - if (this._dataSource && this._dataSource.isInitialized) { - await this._dataSource.destroy(); - this._dataSource = null; + console.info('Database has been initialized!'); } } }