const shared_consts = require('../tools/shared_nodejs'); const cartModel = require('../models/cart'); const { ObjectId } = require('mongodb'); const Gasordine = require('../models/gasordine'); const Order = require('../models/order'); const OrderClass = require('../modules/OrderClass'); const Scontistica = require('../models/scontistica'); class Cart { constructor(order, arrorders) { this.modify_at = new Date(); this.items = {}; if (!!order) { this.initializeFromOrder(order); } else if (!!arrorders) { for (const ord of arrorders) { this.items.push(ord); } } } async updatecarttotals(updateCalcPrice = true) { try { this.totalQty = 0; this.totalPrice = 0; this.totalPriceCalc = 0; this.totalPriceIntero = 0; for (const key in this.items) { const item = this.items[key]; const order = item.order || item; await this.updateOrderTotals(order, updateCalcPrice); } this.totalPrice = parseFloat(this.totalPrice.toFixed(2)); this.totalPriceCalc = parseFloat(this.totalPriceCalc.toFixed(2)); this.totalPriceIntero = parseFloat(this.totalPriceIntero.toFixed(2)); } catch (e) { console.error("Errore durante l'aggiornamento del carrello:", e); } } async init() { await this.updatecarttotals(false); } initializeFromOrder(order) { this.idapp = order.idapp || 0; this.userId = order.userId || ''; this.items[order._id] = order; } static async constructByCart(cart) { try { const mynewcart = new Cart(null); await mynewcart.init(); mynewcart.idapp = cart.idapp || 0; mynewcart.items = cart.items; mynewcart.department = cart.department; mynewcart.userId = cart.userId || ''; mynewcart.modify_at = new Date(); mynewcart.note_ordine_gas = ''; mynewcart.codice_sconto = cart.codice_sconto; mynewcart.descr_sconto = cart.descr_sconto; return mynewcart; } catch (e) { console.log('Error', e); return null; } } isAvailableByOrder(order) { if (order && order.product) { return order.product.quantityAvailable > 0; } return false; } isInPreorderByOrder(order) { if (order && order.product) { return order.product.bookableAvailableQty > 0; } return false; } isSameStorehouse(itemorder) { try { if (this.items.length > 0) { const mystorehouse = this.items[0].order.idStorehouse; return mystorehouse ? mystorehouse._id.toString() === itemorder.idStorehouse : true; } else { return true; } } catch (e) { return false; } } async addqty(itemorder) { const myitem = this.items.find((rec) => rec.order._id.toString() === itemorder._id); if (!!myitem) { let stepmin = myitem.order?.product?.minStepQty || 1; let step = stepmin; if (this.isAvailableByOrder(myitem.order)) { if (myitem.order.quantity === 0) step = myitem.order.product.minBuyQty ?? stepmin; else if (myitem.order.quantity >= 10) step = stepmin < 2 ? 2 : stepmin; else if (myitem.order.quantity >= 20) step = stepmin < 5 ? 5 : stepmin; myitem.order.quantity += step; } else { if (myitem.order.quantitypreordered === 0) step = myitem.order.product.minBuyQty ?? stepmin; else if (myitem.order.quantitypreordered >= 10) step = stepmin < 2 ? 2 : stepmin; else if (myitem.order.quantitypreordered >= 20) step = stepmin < 5 ? 5 : stepmin; myitem.order.quantitypreordered += step; } myitem.order.modify_at = new Date(); myitem.order = await Order.updateTotals(myitem.order, this.codice_sconto); await this.updatecarttotals(false); await this.updateExtraOrder(); await Order.findOneAndUpdate({ _id: myitem.order._id }, { $set: myitem.order }, { new: false }); return myitem.order; } } qtaNextSub(myorder, myproduct) { try { let step = myproduct.minStepQty || 1; let minqta = myproduct.minBuyQty || 1; if (myproduct.quantityAvailable > 0) { if (myorder.quantity === minqta) { step = minqta; } else { if (myorder.quantity - step < 0) { step = myorder.quantity - step; } } } else { if (myorder.quantitypreordered === minqta) { step = minqta; } step = myorder.quantity - stepΩ; } return step; } catch (e) { console.error('Error in qtaNextSub: ', e); return 0; // default step value in case of error } } async subqty(itemorder) { try { const myitem = this.items.find((rec) => rec.order._id.toString() === itemorder._id); if (!!myitem) { let step = this.qtaNextSub(myitem.order, myitem.order.product); if (myitem.order.quantitypreordered - step >= 0) { myitem.order.quantitypreordered -= step; } else { if (myitem.order.quantity - step >= 0) { myitem.order.quantity -= step; } } myitem.order = await Order.updateTotals(myitem.order, this.codice_sconto); await this.updatecarttotals(false); await this.updateExtraOrder(); await Order.findOneAndUpdate({ _id: myitem.order._id }, { $set: myitem.order }, { new: false }); return myitem.order; } } catch (e) { console.error('Err: ', e); } } async addItem(itemorder) { // this.items.push(itemorder); let ind = this.items.length; this.items[ind] = {}; this.items[ind].order = itemorder; this.items[ind].order = await Order.updateTotals(this.items[ind].order, this.codice_sconto); await this.updatecarttotals(false); await this.updateExtraOrder(); return ind; } async removeItem(orderId) { // this.items.push(itemorder); this.items = this.items.filter((item) => item.order._id.toString() !== orderId.toString()); await this.updatecarttotals(false); await this.updateExtraOrder(); } generateModel() { try { let newCart = new cartModel({ idapp: this.idapp, items: this.generateArray(), totalQty: this.totalQty, totalPriceCalc: this.totalPriceCalc, totalPriceIntero: this.totalPriceIntero, totalPrice: this.totalPrice, userId: this.userId, department: this.department, note: this.note, codice_sconto: this.codice_sconto, descr_sconto: this.descr_sconto, note_ordine_gas: this.note_ordine_gas, modify_at: this.modify_at, }); return newCart; } catch (e) { console.error('Err', e); } return null; } async updateOrderTotals(order, updateCalcPrice) { order.TotalPriceProductCalc = 0; // PROVO A METTERE SEMPRE CHE MI RICALCOLA IL PREZZO ! // updateCalcPrice = true; if (updateCalcPrice) { order.TotalPriceProduct = 0; } const qty = order.quantity + order.quantitypreordered; this.totalQty += qty; const recscontisticheTrovate = await Cart.getRecSconto(this.idapp, this.codice_sconto, true); const scontiDaUsare = recscontisticheTrovate?.length ? recscontisticheTrovate : order.scontisticas || []; const priceCalc = this.calcolaPrezzoScontato(order, qty, scontiDaUsare); const priceintero = this.calcolaPrezzoScontato(order, qty, []); order.TotalPriceProductCalc += priceCalc; if (updateCalcPrice) { order.TotalPriceProduct += priceCalc; order.TotalPriceProductstr = parseFloat(order.TotalPriceProduct.toFixed(2)); } this.totalPrice += order.TotalPriceProduct; this.totalPriceCalc += priceCalc; this.totalPriceIntero += priceintero; // if (updateCalcPrice) { // Aggiorna anche l'ordine associato await Order.findOneAndUpdate({ _id: order._id }, { $set: order }, { new: false }); // } } calcolaPrezzoScontato(order, qtyTotale, sconti = []) { if (!sconti || sconti.length === 0) { return order.price * qtyTotale; } const { sconti_da_applicare, qtanonscontata } = OrderClass.applyNonCumulativeDiscounts(order, sconti); const prezzoTotale = OrderClass.calculateDiscountedPrice(order, sconti_da_applicare, qtanonscontata); return prezzoTotale; } async updateExtraOrder() { try { let arrGas = []; const precnoteordgas = this.note_ordine_gas; this.note_ordine_gas = ''; for (const rec in this.items) { let order = this.items[rec].order; if (!order) { order = this.items[rec]; } // Prendo la nota valida e la metto visibile sul Carrello ! if (order.idGasordine) { const recGas = await Gasordine.findOne({ _id: order.idGasordine }).lean(); if (recGas) { if (recGas.note_ordine_gas) { if (!arrGas.includes(recGas._id.toString())) { if (this.note_ordine_gas) this.note_ordine_gas += '
'; this.note_ordine_gas += '' + recGas.name + '' + ':
' + recGas.note_ordine_gas; arrGas.push(recGas._id.toString()); } } } } } } catch (e) { console.error('Err:', e); } } generateArray() { let arr = []; for (let id in this.items) { arr.push(this.items[id]); } return arr; } static async getRecSconto(idapp, codice_sconto, soloAttivi) { const condSconto = { $regex: new RegExp(`^${codice_sconto}$`, 'i') }; const query = { idapp: idapp, code: condSconto, applica: shared_consts.SCONTI_APPLICA.A_TUTTI, }; if (soloAttivi) { query.attivo = true; } const recscontisticheTrovate = await Scontistica.find(query).lean(); return recscontisticheTrovate; } async updateCartIntoDB() { const result = await cartModel.updateCartByUserId(this.userId, { items: this.items, totalQty: this.totalQty, totalPrice: this.totalPrice, totalPriceCalc: this.totalPriceCalc, totalPriceIntero: this.totalPriceIntero, userId: this.userId, }); return result; } async aggiornaCarrello() { try { // Rifai i calcoli ! await this.updatecarttotals(true); await this.updateExtraOrder(); // Aggiorna i calcoli sul DB: const mycart = await this.updateCartIntoDB(); // ritorna il carrello aggiornato ! return await cartModel.getCartCompletoByCartId(mycart._id, this.idapp); } catch (e) { console.error("Errore durante l'aggiornamento del carrello:", e); } } } module.exports = Cart;