Skip to content

Commit

Permalink
Implement pay amount on complete order
Browse files Browse the repository at this point in the history
  • Loading branch information
akbarsaputrait committed Oct 27, 2024
1 parent 2d50888 commit ee03f16
Show file tree
Hide file tree
Showing 7 changed files with 228 additions and 327 deletions.
162 changes: 5 additions & 157 deletions src/app/owner/restaurant/order/detail.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`)
Expand All @@ -196,14 +42,16 @@ 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()) {
throw new ValidationException(validation);
}

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);
Expand Down
3 changes: 0 additions & 3 deletions src/app/owner/restaurant/order/order.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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}`)
Expand Down
Loading

0 comments on commit ee03f16

Please sign in to comment.