feat: agregar factor de conversión y ajustar gestión de stock en el carrito

This commit is contained in:
Juan Felipe Zapata Moreno 2026-02-24 18:43:21 -06:00
parent cf80e914fd
commit 44d86af459
4 changed files with 30 additions and 6 deletions

View File

@ -60,6 +60,7 @@ const confirmSelection = () => {
unit_of_measure_id: selectedOption.value.unit_of_measure_id, unit_of_measure_id: selectedOption.value.unit_of_measure_id,
unit_price: selectedOption.value.unit_price, unit_price: selectedOption.value.unit_price,
unit_name: selectedOption.value.unit_of_measure_id ? selectedOption.value.unit_name : null, unit_name: selectedOption.value.unit_of_measure_id ? selectedOption.value.unit_name : null,
conversion_factor: selectedOption.value.conversion_factor
}); });
selectedOption.value = null; selectedOption.value = null;
}; };

View File

@ -209,7 +209,7 @@ const addToCart = async (product) => {
// Si el producto ya está en el carrito (sin seriales), solo incrementar sin abrir selectores // Si el producto ya está en el carrito (sin seriales), solo incrementar sin abrir selectores
const existingItem = cart.items.find(i => i.item_key === 'p:' + product.id); const existingItem = cart.items.find(i => i.item_key === 'p:' + product.id);
if (existingItem && !existingItem.track_serials) { if (existingItem && !existingItem.track_serials) {
if (existingItem.quantity < product.stock) { if (existingItem.quantity < existingItem.max_stock) {
existingItem.quantity++; existingItem.quantity++;
window.Notify.success(`${product.name} agregado al carrito`); window.Notify.success(`${product.name} agregado al carrito`);
} else { } else {
@ -536,12 +536,21 @@ const handleConfirmSale = async (paymentData) => {
}; };
}); });
const unitMap = {};
cart.items.filter(i => !i.is_bundle && i.unit_of_measure_id).forEach(item => {
unitMap[item.inventory_id] = {
unit_name: item.unit_name,
quantity: item.quantity
};
});
// Generar ticket PDF con descarga automática e impresión // Generar ticket PDF con descarga automática e impresión
await ticketService.generateSaleTicket(response, { await ticketService.generateSaleTicket(response, {
businessName: 'HIKVISION DISTRIBUIDOR', businessName: 'HIKVISION DISTRIBUIDOR',
autoDownload: true, autoDownload: true,
autoPrint: false, autoPrint: false,
bundleMap bundleMap,
unitMap
}); });
window.Notify.success('Ticket generado e impreso correctamente'); window.Notify.success('Ticket generado e impreso correctamente');

View File

@ -80,7 +80,8 @@ const ticketService = {
businessName = 'HIKVISION DISTRIBUIDOR', businessName = 'HIKVISION DISTRIBUIDOR',
autoDownload = true, autoDownload = true,
autoPrint = false, autoPrint = false,
bundleMap = {} bundleMap = {},
unitMap = {}
} = options; } = options;
// Detectar ubicación del usuario // Detectar ubicación del usuario
@ -322,14 +323,24 @@ const ticketService = {
} }
// Cantidad y Precio // Cantidad y Precio
const quantity = item.quantity || 1; const unitInfo = unitMap[item.inventory_id];
const displayQty = unitInfo?.quantity
?? ((item.unit_of_measure_id && item.unit_quantity)
? parseFloat(item.unit_quantity)
: (item.quantity || 1));
const unitAbbr = unitInfo?.unit_name
|| (item.unit_of_measure_id
? (item.unit_of_measure?.abbreviation || item.unit_of_measure?.name || '')
: '');
const qtyText = unitAbbr ? `${displayQty} ${unitAbbr}` : String(displayQty);
const unitPrice = formatMoney(item.unit_price); const unitPrice = formatMoney(item.unit_price);
doc.setFontSize(8); doc.setFontSize(8);
doc.setFont('helvetica', 'normal'); doc.setFont('helvetica', 'normal');
doc.setTextColor(...blackColor); doc.setTextColor(...blackColor);
doc.text(String(quantity), 52, yPosition, { align: 'center' }); doc.text(qtyText, 52, yPosition, { align: 'center' });
doc.text(`$${unitPrice}`, rightMargin, yPosition, { align: 'right' }); doc.text(`$${unitPrice}`, rightMargin, yPosition, { align: 'right' });
yPosition += 4; yPosition += 4;

View File

@ -68,6 +68,9 @@ const useCart = defineStore('cart', {
? parseFloat(config.unit_price) ? parseFloat(config.unit_price)
: parseFloat(product.price?.retail_price || 0); : parseFloat(product.price?.retail_price || 0);
const conversionFactor = parseFloat(config?.conversion_factor || 1);
const maxStock = conversionFactor !== 1 ? Math.floor(product.stock / conversionFactor) : product.stock;
// Agregar nuevo item // Agregar nuevo item
this.items.push({ this.items.push({
item_key: key, item_key: key,
@ -79,7 +82,7 @@ const useCart = defineStore('cart', {
quantity: 1, quantity: 1,
unit_price: unitPrice, unit_price: unitPrice,
tax_rate: parseFloat(product.price?.tax || 16), tax_rate: parseFloat(product.price?.tax || 16),
max_stock: product.stock, max_stock: maxStock,
// Campos para seriales // Campos para seriales
track_serials: product.track_serials || false, track_serials: product.track_serials || false,
serial_numbers: config?.serialNumbers || [], serial_numbers: config?.serialNumbers || [],