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 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; 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)); } 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; 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); 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); 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 = Order.updateTotals(this.items[ind].order); 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, totalPrice: this.totalPrice, userId: this.userId, department: this.department, note: this.note, codice_sconto: this.codice_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; if (updateCalcPrice) { order.TotalPriceProduct = 0; } const qty = order.quantity + order.quantitypreordered; this.totalQty += qty; let recscontisticheTrovate = await Scontistica.find({ idapp: order.idapp, code: this.codice_sconto?.toUpperCase(), applica: shared_consts.SCONTI_APPLICA.A_TUTTI, }).lean(); const scontiDaUsare = recscontisticheTrovate?.length ? recscontisticheTrovate : order.scontisticas || []; const priceCalc = this.calcolaPrezzoScontato(order, qty, scontiDaUsare); order.TotalPriceProductCalc += priceCalc; if (updateCalcPrice) { order.TotalPriceProduct += priceCalc; order.TotalPriceProductstr = parseFloat(order.TotalPriceProduct.toFixed(2)); } this.totalPriceCalc += priceCalc; this.totalPrice += order.TotalPriceProduct; } calcolaPrezzoScontato(order, qtyTotale, sconti = []) { if (!sconti || sconti.length === 0) { return order.price * qtyTotale; } let scontiApplicati = []; let qtaRimanente = qtyTotale; let qtaNonScontata = 0; // Applica sconti non cumulativi while (qtaRimanente > 0) { let scontoScelto = null; for (const sconto of sconti.filter((s) => !s.cumulativo)) { if (qtaRimanente >= s.qta) { scontoScelto = { ...sconto, qtadascontare: s.qta }; break; // prendi il primo valido (puoi migliorare scegliendo il più vantaggioso) } } if (scontoScelto) { scontiApplicati.push(scontoScelto); qtaRimanente -= scontoScelto.qtadascontare; } else { qtaNonScontata = qtaRimanente; qtaRimanente = 0; } } let prezzoTotale = 0; for (const sconto of scontiApplicati) { if (sconto.perc_sconto > 0) { prezzoTotale += sconto.qtadascontare * order.price * (1 - sconto.perc_sconto / 100); } else if (sconto.price > 0) { prezzoTotale += sconto.price; } } if (qtaNonScontata > 0) { prezzoTotale += qtaNonScontata * order.price; } 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; } } module.exports = Cart;