Applied tax in order API(Node+MongoDB)
Tags: backend, javascript, node, mongodb
Published: 2023-08-27 17:51:40

Suppose i have below Data:

```
let result = [
  {
    InvoiceID: ORD001,
    orders: [
      {
        taxType: {
          _id: "64e20a255366cca58c047ce9",
          taxName: "Percentage Tax",
          percentage: 2,
          amount: null,
        },

        Name: "Yogurt",
        category: "Dairy Products",
        quantity: 1,
        price: 100,
        appliedTaxAmount: null,
      },
      {
        taxType: {
          _id: "64e20a255366cca58c047ce9",
          taxName: "Amount Tax",
          percentage: null,
          amount: 2,
        },

        Name: "Campa Cola",
        category: "Cold Drinks",
        quantity: 5,
        price: 50,
        appliedTaxAmount: null,
      },
    ],
  },
  {
    InvoiceID: ORD002,
    orders: [
      {
        taxType: {
          _id: "64e20a255366cca58c047ce9",
          taxName: "Amount Tax",
          percentage: null,
          amount: 3,
        },

        Name: "",
        category: "Snacks",
        quantity: 10,
        price: 10,
        appliedTaxAmount: null,
      },
      {
        taxType: {
          _id: "64e20a255366cca58c047ce9",
          taxName: "Percentage Tax",
          percentage: 10,
          amount: null,
        },

        Name: "Campa Cola",
        category: "Cold Drinks",
        quantity: 2,
        price: 10,
        appliedTaxAmount: null,
      },
    ],
  },
];
```
To calculate the appliedTaxAmount for each order and add the priceWithTax field to each object, you can use the following JavaScript code:

```
function calcTax(info) {
  for (const data of result) {
    for (const item of data.orders) {
      if (item.taxType.amount === null) {
        item.appliedTaxAmount =
          (item.price * item.quantity * item.taxType.percentage) / 100;
      } else if (item.taxType.percentage === null) {
        item.appliedTaxAmount = item.quantity * item.taxType.amount;
      }

      item.priceWithTax = item.price * item.quantity + item.appliedTaxAmount;
    }
  }
  return info;
}
const response = calcTax(result);
console.log(JSON.stringify(response, null, 2));
```
You can also achieve similar calculations using MongoDB's aggregation framework. Below is the code:

```
db.collectionName.aggregate([
  {
    $unwind: "$orders"
  },
  {
    $addFields: {
      "orders.appliedTaxAmount": {
        $cond: {
          if: { $ne: ["$orders.taxType.percentage", null] },
          then: {
            $multiply: [
              "$orders.price",
              "$orders.taxType.percentage",
              "$orders.quantity",
              0.01
            ]
          },
          else: {
            $multiply: ["$orders.taxType.amount", "$orders.quantity"]
          }
        }
      },
      "orders.priceWithTax ": {
        $add: [
          { $multiply: ["$orders.price", "$orders.quantity"] },
          "$orders.appliedTaxAmount"
        ]
      }
    }
  },
  {
    $group: {
      _id: "$InvoiceID",
      InvoiceID: { $first: "$InvoiceID" },
      orders: { $push: "$orders" }
    }
  },
  {
    $group: {
      _id: null,
      result: { $push: "$$ROOT" }
    }
  },
  {
    $project: {
      _id: 0,
      result: 1
    }
  }
])

```
The response will be in the form of a JSON document containing an array named result:

```
{
  "result": [
    {
      "InvoiceID": ORD001,
      "orders": [
        {
          "taxType": {
            "_id": "64e20a255366cca58c047ce9",
            "taxName": "TaxOne",
            "percentage": 2,
            "amount": null
          },
          "Name": "Yogurt",
          "category": "Dairy Products",
          "quantity": 1,
          "price": 100,
          "appliedTaxAmount": 2,
          "priceWithTax": 102
        },
        {
          "taxType": {
            "_id": "64e20a255366cca58c047ce9",
            "taxName": "TaxTwo",
            "percentage": null,
            "amount": 2
          },
          "Name": "Campa Cola",
          "category": "Cold Drinks",
          "quantity": 5,
          "price": 50,
          "appliedTaxAmount": 10,
          "priceWithTax": 60
        }
      ]
    },
    {
      "InvoiceID": ORD002,
      "orders": [
        {
          "taxType": {
            "_id": "64e20a255366cca58c047ce9",
            "taxName": "Amount Tax",
            "percentage": null,
            "amount": 3
          },
          "Name": "",
          "category": "Snacks",
          "quantity": 10,
          "price": 10,
          "appliedTaxAmount": 30,
          "priceWithTax": 130
        },
        {
          "taxType": {
            "_id": "64e20a255366cca58c047ce9",
            "taxName": "TaxThree",
            "percentage": 10,
            "amount": null
          },
          "Name": "Campa Cola",
          "category": "Cold Drinks",
          "quantity": 2,
          "price": 10,
          "appliedTaxAmount": 2,
          "priceWithTax": 22
        }
      ]
    }
  ]
}

```
Above aggregation pipeline performs the following steps:

1. **$unwind**: Unwinds the orders array to create separate documents for each order line.
2. **$addFields**: Adds the calculated fields appliedTaxAmountand priceWithTax to each order line. 
3. **$group**: Groups the data by InvoiceID, preserving the orders within each order. 
4. Another **$group**: Groups all the orders into a single result array.
5. **$project**: Projects only the result field, removing the _id.