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_price: selectedOption.value.unit_price,
unit_name: selectedOption.value.unit_of_measure_id ? selectedOption.value.unit_name : null,
conversion_factor: selectedOption.value.conversion_factor
});
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
const existingItem = cart.items.find(i => i.item_key === 'p:' + product.id);
if (existingItem && !existingItem.track_serials) {
if (existingItem.quantity < product.stock) {
if (existingItem.quantity < existingItem.max_stock) {
existingItem.quantity++;
window.Notify.success(`${product.name} agregado al carrito`);
} 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
await ticketService.generateSaleTicket(response, {
businessName: 'HIKVISION DISTRIBUIDOR',
autoDownload: true,
autoPrint: false,
bundleMap
bundleMap,
unitMap
});
window.Notify.success('Ticket generado e impreso correctamente');

View File

@ -80,7 +80,8 @@ const ticketService = {
businessName = 'HIKVISION DISTRIBUIDOR',
autoDownload = true,
autoPrint = false,
bundleMap = {}
bundleMap = {},
unitMap = {}
} = options;
// Detectar ubicación del usuario
@ -322,14 +323,24 @@ const ticketService = {
}
// 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);
doc.setFontSize(8);
doc.setFont('helvetica', 'normal');
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' });
yPosition += 4;

View File

@ -68,6 +68,9 @@ const useCart = defineStore('cart', {
? parseFloat(config.unit_price)
: 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
this.items.push({
item_key: key,
@ -79,7 +82,7 @@ const useCart = defineStore('cart', {
quantity: 1,
unit_price: unitPrice,
tax_rate: parseFloat(product.price?.tax || 16),
max_stock: product.stock,
max_stock: maxStock,
// Campos para seriales
track_serials: product.track_serials || false,
serial_numbers: config?.serialNumbers || [],