Untitled

 avatar
user_6004366
javascript
a year ago
5.7 kB
5
Indexable
// Update an existing sale
const updateSale = async (req, res, next) => {
  const { id } = req.params;
  const transaction = await sequelize.transaction();

  try {
    const validatedUpdates = partialSaleSchema.parse(req.body);

    const sale = await models.Sale.findOne({
      where: { id },
      include: [{ model: models.SoldItem, as: "SoldItems" }],
      transaction,
    });

    if (!sale) {
      await transaction.rollback();
      return res.status(404).json({ status: 404, message: "Sale not found" });
    }

    const updates = {};
    let totalPrice = sale.totalPrice;
    const oldPrice = sale.totalPrice;
    let debtAdjustment = 0;

    // Handle discount update
    if (validatedUpdates.discount !== undefined) {
      totalPrice += sale.discount;
      updates.discount = validatedUpdates.discount;
      totalPrice -= validatedUpdates.discount;
      debtAdjustment = sale.discount - validatedUpdates.discount;
    }

    // Handle paid amount update
    if (validatedUpdates.paidAmount !== undefined) {
      const previousPaidAmount = sale.paidAmount;
      updates.paidAmount = validatedUpdates.paidAmount;
      debtAdjustment += previousPaidAmount - validatedUpdates.paidAmount;
    }

    if (validatedUpdates.soldItems) {
      const newSoldItems = validatedUpdates.soldItems.map((item) => ({
        ...item,
        sale_id: sale.id,
      }));

      // Revert old quantities
      for (const existingItem of sale.SoldItems) {
        const product = await models.Item.findOne({
          where: { id: existingItem.item_id },
          transaction,
        });

        if (product) {
          product.quantity += existingItem.quantity; // Revert quantity
          product.quantitySold -= existingItem.quantity; // Revert quantitySold
          await product.save({ transaction });
        }
      }

      // Update new sold items quantities
      for (const newItem of newSoldItems) {
        const existingItem = sale.SoldItems.find(
          (item) => item.item_id === newItem.item_id
        );

        const product = await models.Item.findOne({
          where: { id: newItem.item_id },
          transaction,
        });
        if (!product || product.deletedAt) {
          await transaction.rollback();
          return res.status(404).json({
            status: 404,
            message: `Item with id ${newItem.item_id} not found`,
          });
        }

        const salePrice =
          newItem.salePrice !== undefined
            ? newItem.salePrice
            : parseFloat(product.salePrice);

        if (existingItem) {
          const quantityDifference = newItem.quantity - existingItem.quantity;
          const salePriceDifference = salePrice - existingItem.salePrice;

          totalPrice += quantityDifference * existingItem.salePrice;
          totalPrice += newItem.quantity * salePriceDifference;

          product.quantity -= newItem.quantity; // Decrease quantity
          product.quantitySold += newItem.quantity; // Increase quantitySold
          await product.save({ transaction });

          await existingItem.update(
            {
              ...newItem,
              price: parseFloat(product.salePrice),
              salePrice: salePrice,
            },
            { transaction }
          );
        } else {
          totalPrice += newItem.quantity * salePrice;

          console.log(
            `Adding new item ID ${newItem.item_id}: ` +
              `-${newItem.quantity} to quantity, ` +
              `+${newItem.quantity} to quantitySold`
          );
          product.quantity -= newItem.quantity; // Decrease quantity
          product.quantitySold += newItem.quantity; // Increase quantitySold
          await product.save({ transaction });

          await models.SoldItem.create(
            {
              ...newItem,
              price: parseFloat(product.salePrice),
              salePrice: salePrice,
            },
            { transaction }
          );
        }
      }

      // Delete removed items from sale
      const existingItemIds = sale.SoldItems.map((item) => item.item_id);
      const newItemIds = newSoldItems.map((item) => item.item_id);
      const itemsToDelete = existingItemIds.filter(
        (id) => !newItemIds.includes(id)
      );

      for (const idToDelete of itemsToDelete) {
        const itemToDelete = sale.SoldItems.find(
          (item) => item.item_id === idToDelete
        );

        totalPrice -= itemToDelete.quantity * itemToDelete.salePrice;
        await itemToDelete.destroy({ transaction });
      }
    }

    const changes = Object.keys(updates).some(
      (key) => updates[key] !== sale[key]
    );

    if (changes || validatedUpdates.soldItems) {
      updates.totalPrice = totalPrice;
      await sale.update(updates, { transaction });

      // Calculate the correct total debt adjustment
      const totalDebtAdjustment = totalPrice - oldPrice + debtAdjustment;

      await updateDebt(sale.customer_id, totalDebtAdjustment, transaction);
      await transaction.commit();

      const updatedSale = await getSaleDetails(sale);

      return res.status(200).json({
        status: 200,
        data: updatedSale,
        message: "Sale updated successfully",
      });
    } else {
      await transaction.rollback();
      return res.status(200).json({
        status: 200,
        data: sale,
        message: "No changes made to sale",
      });
    }
  } catch (error) {
    if (transaction && !transaction.finished) {
      await transaction.rollback();
    }

    if (error.message.includes("Item with id")) {
      return res.status(404).json({ status: 404, message: error.message });
    }

    next(error);
  }
};
Editor is loading...
Leave a Comment