Source: order/index.js

/**
 * Represents an order in the system, encapsulating all necessary details
 * and logic to manage items, discounts, and bill calculations. This class
 * provides methods to add, cancel, or modify items in the order, as well as
 * track the status and customer-related information.
 *
 * The class supports the following functionalities:
 * - Add items to the order.
 * - Add extra items to the order.
 * - Cancel items from the order.
 * - Confirm requested items to be added to the order.
 * - Cancel the entire order and reset all related items and status.
 * - Set and apply a discount to the total bill.
 * - Recalculate the bill amount when items or discounts are modified.
 *
 * The order maintains various properties to manage the order's state,
 * including the unique order ID, bill number, status, discount, customer details,
 * and timestamps for creation and updates.
 *
 * @class
 */
class Order {
  /**
   * Creates an order instance.
   * @pram {string} orderId - Unique Identifier for the order
   * @pram {string} billNo - Bill number associated with the order.
   * @pram {number} discount - Discount applied to the order.
   * @pram {string} status - status of the order (e.g., "pending","completed").
   * @pram {string} tabelVpa - Virtual Payment Address for table-based orders.
   * @pram {Customer} customer - Customer associated with order.
   * @pram {string} onlineOrderCode - Code For online orders.
   */
  constructor(
    orderId,
    billNo,
    discount,
    status,
    tabelVpa,
    customer,
    onlineOrderCode
  ) {
    this.uniqueId = orderId;
    this.billAmount = 0;
    this.billNo = billNo;
    this.discount = discount;
    this.status = status;
    this.tablevpa = this.tablevpa;
    this.createdAt = new Date();
    this.updatedAt = new Date();
    this.customer = customer;
    this.onlineOrderCode = onlineOrderCode;
    this.cancelItems = [];
    this.extraItems = [];
    this.items = [];
    this.requestedItems = [];
  }

  /**
   * Adds a new item to the list of items and recalculates the bill amount.
   *
   * This function pushes the provided item to the `items` array and invokes
   * the `calculateBillAmount()` method to ensure the total bill amount is updated
   * whenever a new item is added. It assumes the `items` array is an existing
   * array holding the list of items and `calculateBillAmount()` is a method
   * that performs the necessary calculation based on the current items.
   *
   * @param {Object} item - The item to be added to the bill. This should be an object
   *                        representing the item, such as an item with properties like
   *                        `name`, `price`, etc.
   *
   * @returns {void}
   */
  addItems(item) {
    this.items.push(item);
    this.calculateBillAmount();
  }
  /**
   * Adds extra items to the order and updates the bill amount.
   * @param {Array} items - List of extra items to add. 
   */
  addExtra(item) {
    this.extraItems.push(item);
    this.calculateBillAmount();
  }
  /**
   * Cancels an item from the order and moves it to the canceled items list.
   * @param {Objects} item -Item to be canceled.
   */
  cancelItem(item) {
    const index = this.items.indexOf(item);
    if (index !== -1) {
      this.cancelItems.push(item);
      this.items.splice(index, 1);
      this.calculateBillAmount();
    }
  }
  /**
   * conforms the requested items and adds them to the main order items.
   */
  confirmRequestedItems() {
    this.items.push(...this.requestedItems);
    this.requestedItems = [];
    this.calculateBillAmount();
  }
  /**
   * Cancels the order by updating its status.
   */
  cancelOrder() {
    this.cancelItems.push(
      ...this.items,
      ...this.extraItems,
      ...this.requestedItems
    );
    this.items = [];
    this.extraItems = [];
    this.requestedItems = [];
    this.status = "canceledOrder";
    this.billAmount = 0;
    this.updatedAt = new Date();
  }
  /**
   * Sets a discounts for the order and calculates the bill amount.
   * @param {number} amount - Discount amount to apply.
   */
  setDiscount(amount) {
    this.discount = amount;
    this.calculateBillAmount();
  }
  /**
   * Calculates the total bill amount based on items and discount.
   */
  calculateBillAmount() {
    let total = this.items.reduce((sum, item) => sum + item.getTotalPrice(), 0);
    total += this.extraItems.reduce(
      (sum, item) => sum + item.getTotalPrice(),
      0
    );
    this.billAmount = total - this.discount;
    this.updatedAt = new Date();
  }
}

export default Order;