diff --git a/almeira-store-app/src/app/api/webhook/whatsapp/route.ts b/almeira-store-app/src/app/api/webhook/whatsapp/route.ts index ae1555b..3227db1 100644 --- a/almeira-store-app/src/app/api/webhook/whatsapp/route.ts +++ b/almeira-store-app/src/app/api/webhook/whatsapp/route.ts @@ -1,29 +1,20 @@ import { NextResponse } from 'next/server'; import { dataService } from '@/lib/data-service'; import { parseSupplierMessage } from '@/lib/gemini-parser'; -import { SupplierPost, Product } from '@/types'; -import { calculateRetailPrice } from '@/lib/pricing-engine'; +import { SupplierPost } from '@/types'; export async function GET() { const posts = dataService.getSupplierPosts(); - const settings = dataService.getSettings(); - return NextResponse.json({ - success: true, - autoPublishEnabled: settings.autoPublishSupplierPosts ?? true, - postsCount: posts.length, - posts, - }); + return NextResponse.json({ success: true, posts }); } export async function POST(request: Request) { try { const payload = await request.json(); - console.log('📥 [WhatsApp Webhook] Mensaje recibido:', JSON.stringify(payload).slice(0, 300)); + console.log('📥 Webhook Evolution API recibido:', JSON.stringify(payload).slice(0, 300)); const data = payload.data || payload; - const settings = dataService.getSettings(); - // 1. Extraer texto del mensaje de WhatsApp const messageContent = data.message?.conversation || data.message?.extendedTextMessage?.text || @@ -31,117 +22,27 @@ export async function POST(request: Request) { data.text || ''; - // 2. Extraer nombre del canal o grupo - const senderPhone = data.key?.remoteJid?.replace(/\D/g, '') || ''; - const isGroup = data.key?.remoteJid?.includes('g.us'); const channelName = - data.groupInfo?.subject || data.pushName || - (isGroup ? 'Grupo Mayorista WhatsApp' : 'Chat Proveedor Directo'); + data.groupInfo?.subject || + (data.key?.remoteJid?.includes('g.us') ? 'Canal Mayorista Entrada' : 'Recepción Directa'); - if (!messageContent || messageContent.trim().length < 6) { - return NextResponse.json({ - success: true, - ignored: 'Mensaje sin texto suficiente para extraer calzado.', - }); + if (!messageContent || messageContent.trim().length < 5) { + return NextResponse.json({ success: true, ignored: 'Mensaje vacío o sin texto relevante' }); } - // 3. Buscar proveedor asociado por teléfono o grupo - const suppliers = dataService.getSuppliers(); - const matchedSupplier = suppliers.find( - (s) => - s.phone.includes(senderPhone) || - (channelName && s.name.toLowerCase().includes(channelName.toLowerCase())) || - (channelName && channelName.toLowerCase().includes(s.name.toLowerCase())) - ); - - const supplierName = matchedSupplier?.name || channelName; - const supplierPhone = matchedSupplier?.phone || senderPhone || '573167455877'; - - // 4. Procesar y extraer información con Gemini AI + // Parsear con Gemini AI const extracted = await parseSupplierMessage(messageContent); - // Recalcular precio con el margen y redondeo al $5.000 oficial - const finalRetailPrice = calculateRetailPrice( - extracted.supplierPrice, - settings.defaultProfitMargin || 35 - ); - - // Extraer imágenes (si Evolution API envió imagen adjunta o usar fotos de alta resolución) - const images: string[] = []; - if (data.message?.imageMessage?.url) { - images.push(data.message.imageMessage.url); - } else { - images.push( - 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80' - ); - } - - // 5. Verificar Anti-Duplicados en el Catálogo - const existingProducts = dataService.getProducts(); - const duplicateProduct = existingProducts.find( - (p) => p.name.toLowerCase() === extracted.name.toLowerCase() - ); - - let registeredProduct: Product | null = null; - const autoPublish = settings.autoPublishSupplierPosts ?? true; - - if (autoPublish) { - if (duplicateProduct) { - // Actualizar stock y tallas existentes sin duplicar - const mergedSizes = Array.from(new Set([...duplicateProduct.sizes, ...extracted.sizes])); - registeredProduct = dataService.updateProduct(duplicateProduct.id, { - supplierPrice: extracted.supplierPrice, - retailPrice: finalRetailPrice, - sizes: mergedSizes, - inStock: true, - isActive: true, - supplierName, - supplierPhone, - }); - console.log(`🔄 [Auto-Sync] Zapatilla "${extracted.name}" actualizada en catálogo (Anti-Duplicados).`); - } else { - // Registrar y publicar automáticamente - registeredProduct = dataService.addProduct({ - name: extracted.name, - brand: extracted.brand, - supplierPrice: extracted.supplierPrice, - retailPrice: finalRetailPrice, - originalPrice: Math.round(finalRetailPrice * 1.35), - sizes: extracted.sizes, - images, - description: `Zapatillas ${extracted.brand} ${extracted.name} garantizadas. Calidad seleccionada con horma nacional y suela antideslizante.`, - category: extracted.category || 'Sneakers / Urbano', - inStock: true, - isActive: true, - isFlashDeal: true, - rating: 4.9, - reviewsCount: 15, - salesCount: 30, - originBadge: 'Bodega Mayorista', - supplierId: matchedSupplier?.id || 'sup-auto', - supplierName, - supplierPhone, - }); - console.log(`✨ [Auto-Publish] Nueva zapatilla "${extracted.name}" publicada automáticamente en tienda.`); - } - } - - // 6. Registrar en el historial de publicaciones recibidas const newPost: SupplierPost = { id: `post-${Date.now()}`, - channelName, - supplierName, - supplierPhone, + channelName: data.groupInfo?.subject || channelName, rawMessage: messageContent, - rawImages: images, - extractedProduct: { - ...extracted, - suggestedRetailPrice: finalRetailPrice, - supplierName, - supplierPhone, - }, - status: autoPublish ? 'published_store' : 'pending_review', + rawImages: [ + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: extracted, + status: 'pending_review', receivedAt: 'Justo ahora', }; @@ -149,12 +50,8 @@ export async function POST(request: Request) { return NextResponse.json({ success: true, - autoPublished: autoPublish, - product: registeredProduct, + message: 'Mensaje procesado con IA e ingresado al feed interno', post: newPost, - message: autoPublish - ? `🔥 ¡Zapatilla "${extracted.name}" procesada y publicada AUTOMÁTICAMENTE en la tienda!` - : `Mensaje ingresado al feed para aprobación manual.`, }); } catch (error: any) { console.error('Error procesando webhook de WhatsApp:', error); diff --git a/almeira-store-app/src/lib/data-service.ts b/almeira-store-app/src/lib/data-service.ts index a594e18..11adc8c 100644 --- a/almeira-store-app/src/lib/data-service.ts +++ b/almeira-store-app/src/lib/data-service.ts @@ -1,6 +1,5 @@ import { Product, City, PaymentMethod, Order, SupplierPost, StoreSettings, Supplier, MonitoredWhatsAppGroup, User } from '@/types'; -// Directorio Interno de Proveedores de Zapatillas export const INITIAL_SUPPLIERS: Supplier[] = [ { "id": "sup-jovic", @@ -31,7 +30,6 @@ export const INITIAL_SUPPLIERS: Supplier[] = [ } ]; -// Ciudades configurables (con entrega en 24 horas y política por ciudad) export const INITIAL_CITIES: City[] = [ { id: 'city-cali', @@ -160,7 +158,6 @@ export const INITIAL_PAYMENT_METHODS: PaymentMethod[] = [ }, ]; -// Catálogo Inicial de Sneakers con datos internos del proveedor export const INITIAL_PRODUCTS: Product[] = [ { "id": "snk-real-1", @@ -2064,7 +2061,6 @@ export const INITIAL_PRODUCTS: Product[] = [ } ]; -// Feed inicial de publicaciones de WhatsApp recibidas export const INITIAL_SUPPLIER_POSTS: SupplierPost[] = [ { id: 'post-1', @@ -2114,7 +2110,6 @@ export const INITIAL_SUPPLIER_POSTS: SupplierPost[] = [ }, ]; -// Memoria centralizada de la aplicación export const INITIAL_MONITORED_GROUPS: MonitoredWhatsAppGroup[] = [ { @@ -2143,15 +2138,176 @@ export const INITIAL_MONITORED_GROUPS: MonitoredWhatsAppGroup[] = [ }, ]; +export const INITIAL_ORDERS: Order[] = [ + { + id: 'ORD-8921', + customerName: 'Mateo Valencia', + customerPhone: '3168945120', + address: 'Av 6N # 24N-32 Edificio Granada Real', + cityId: 'city-cali', + cityName: 'Cali (Norte - Granada)', + items: [ + { + productId: 'snk-jordan4-1', + productName: 'Nike Air Jordan 4 Retro White Cement', + brand: 'Jordan', + size: '41', + quantity: 1, + price: 135000, + supplierPrice: 95000, + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + supplierPhone: '573134848203', + image: 'https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 135000, + shippingCost: 0, + totalAmount: 135000, + depositAmount: 10000, + balanceDue: 125000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega Efectivo / Nequi', + status: 'pending', + createdAt: 'Hoy, 06:45 AM', + notes: 'Timbrar en apto 302. Paga con billete de 100 y 50.', + }, + { + id: 'ORD-8922', + customerName: 'Valentina Restrepo', + customerPhone: '3157829401', + address: 'Calle 52N # 4BN-15 Casa 4 La Flora', + cityId: 'city-cali', + cityName: 'Cali (Norte - La Flora)', + items: [ + { + productId: 'snk-vomero5-1', + productName: 'Nike Zoom Vomero 5 Photon Dust Metallic Silver', + brand: 'Nike', + size: '39', + quantity: 1, + price: 130000, + supplierPrice: 90000, + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + supplierPhone: '573134848203', + image: 'https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 130000, + shippingCost: 0, + totalAmount: 130000, + depositAmount: 10000, + balanceDue: 120000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega Nequi', + status: 'pending', + createdAt: 'Hoy, 07:15 AM', + notes: 'Dejar en portería si no contesta.', + }, + { + id: 'ORD-8923', + customerName: 'Santiago Henao', + customerPhone: '3186523910', + address: 'Cra 105 # 14-45 Condominio Portal de la Viga', + cityId: 'city-cali', + cityName: 'Cali (Sur - Ciudad Jardín)', + items: [ + { + productId: 'snk-campus-1', + productName: 'Adidas Campus 00s Core Black White', + brand: 'Adidas', + size: '40', + quantity: 1, + price: 125000, + supplierPrice: 85000, + supplierName: 'EXCLUSIVE CC MÍO 3B', + supplierPhone: '573159876543', + image: 'https://images.unsplash.com/photo-1525966222134-fcfa99b8ae77?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 125000, + shippingCost: 0, + totalAmount: 125000, + depositAmount: 10000, + balanceDue: 115000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega', + status: 'pending', + createdAt: 'Hoy, 07:30 AM', + notes: 'Recibe en horas de la tarde después de las 2 PM.', + }, + { + id: 'ORD-8924', + customerName: 'Camila Ospina', + customerPhone: '3114958203', + address: 'Cra 85E # 14-80 Apto 501 El Ingenio', + cityId: 'city-cali', + cityName: 'Cali (Sur - El Ingenio)', + items: [ + { + productId: 'snk-coach-1', + productName: 'Coach Low Top Monogram Signature Brown', + brand: 'Coach', + size: '38', + quantity: 1, + price: 145000, + supplierPrice: 100000, + supplierName: 'EXCLUSIVE CC MÍO 3B', + supplierPhone: '573159876543', + image: 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 145000, + shippingCost: 0, + totalAmount: 145000, + depositAmount: 10000, + balanceDue: 135000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Separación Pagada Bold', + status: 'deposit_received', + createdAt: 'Hoy, 08:00 AM', + notes: 'Cliente ya pagó $10.000 de anticipo.', + }, + { + id: 'ORD-8925', + customerName: 'Daniel Caicedo', + customerPhone: '3174829105', + address: 'Cra 10 # 3-45 San Antonio', + cityId: 'city-cali', + cityName: 'Cali (Oeste - San Antonio)', + items: [ + { + productId: 'snk-af1-1', + productName: 'Nike Air Force 1 07 Low Triple White', + brand: 'Nike', + size: '42', + quantity: 1, + price: 120000, + supplierPrice: 80000, + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + supplierPhone: '573134848203', + image: 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 120000, + shippingCost: 0, + totalAmount: 120000, + depositAmount: 10000, + balanceDue: 110000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega', + status: 'pending', + createdAt: 'Hoy, 08:20 AM', + }, +]; + class DataService { private products: Product[] = [...INITIAL_PRODUCTS]; private cities: City[] = [...INITIAL_CITIES]; private paymentMethods: PaymentMethod[] = [...INITIAL_PAYMENT_METHODS]; private suppliers: Supplier[] = [...INITIAL_SUPPLIERS]; - private orders: Order[] = []; + private orders: Order[] = [...INITIAL_ORDERS]; private supplierPosts: SupplierPost[] = [...INITIAL_SUPPLIER_POSTS]; - // Productos getProducts(): Product[] { return this.products; } @@ -2178,7 +2334,6 @@ class DataService { return this.products.length < initialLen; } - // Proveedores getSuppliers(): Supplier[] { return this.suppliers; } @@ -2192,7 +2347,6 @@ class DataService { return supplier; } - // Ciudades getCities(): City[] { return this.cities; } @@ -2213,7 +2367,6 @@ class DataService { return this.cities[idx]; } - // Métodos de Pago getPaymentMethods(): PaymentMethod[] { return this.paymentMethods; } @@ -2225,7 +2378,6 @@ class DataService { return this.paymentMethods[idx]; } - // Pedidos getOrders(): Order[] { return this.orders; } @@ -2235,6 +2387,30 @@ class DataService { return order; } + createOrder(orderData: Partial): Order { + const newOrder: Order = { + id: `ord-${Date.now()}`, + customerName: orderData.customerName || 'Cliente', + customerPhone: orderData.customerPhone || '', + address: orderData.address || '', + cityId: orderData.cityId || 'city-cali', + cityName: orderData.cityName || 'Cali', + items: orderData.items || [], + subtotal: orderData.subtotal || 0, + shippingCost: orderData.shippingCost || 0, + totalAmount: orderData.totalAmount || 0, + depositAmount: orderData.depositAmount || 10000, + balanceDue: (orderData.totalAmount || 0) - (orderData.depositAmount || 10000), + paymentMethodId: orderData.paymentMethodId || 'pay-contraentrega', + paymentMethodName: orderData.paymentMethodName || 'Contraentrega', + status: 'pending', + notes: orderData.notes, + createdAt: new Date().toISOString(), + }; + this.orders.unshift(newOrder); + return newOrder; + } + updateOrderStatus(orderId: string, status: Order['status']): Order | null { const order = this.orders.find((o) => o.id === orderId); if (!order) return null; @@ -2242,14 +2418,23 @@ class DataService { return order; } + getSupplierPosts(): SupplierPost[] { + return this.supplierPosts; + } + + addSupplierPost(post: SupplierPost): SupplierPost { + this.supplierPosts.unshift(post); + return post; + } + // Configuración de la Tienda private settings: StoreSettings = { - storeName: 'Almeira Store', - slogan: 'Sneakers & Moda Urbana', + storeName: 'DripZone', + slogan: 'Luxury Streetwear & Collectibles', email: 'carlos.andres.lasso@gmail.com', phone: '3167455877', whatsappNumber: '573167455877', - instagramHandle: '@almeirastore.co', + instagramHandle: '@dripzone.co', address: 'Bodega Central / Cali', city: 'Cali, Colombia', nequiAccount: '316 745 5877', @@ -2291,7 +2476,7 @@ class DataService { { id: 'usr-operator-1', name: 'Andrés Operador Despachos', - email: 'despachos@almeira.com.co', + email: 'despachos@dripzone.co', phone: '3159876543', city: 'Cali', role: 'operator', @@ -2365,7 +2550,6 @@ class DataService { } return null; } - } export const dataService = new DataService(); diff --git a/sneaky-app/src/app/api/webhook/whatsapp/route.ts b/sneaky-app/src/app/api/webhook/whatsapp/route.ts index ae1555b..3227db1 100644 --- a/sneaky-app/src/app/api/webhook/whatsapp/route.ts +++ b/sneaky-app/src/app/api/webhook/whatsapp/route.ts @@ -1,29 +1,20 @@ import { NextResponse } from 'next/server'; import { dataService } from '@/lib/data-service'; import { parseSupplierMessage } from '@/lib/gemini-parser'; -import { SupplierPost, Product } from '@/types'; -import { calculateRetailPrice } from '@/lib/pricing-engine'; +import { SupplierPost } from '@/types'; export async function GET() { const posts = dataService.getSupplierPosts(); - const settings = dataService.getSettings(); - return NextResponse.json({ - success: true, - autoPublishEnabled: settings.autoPublishSupplierPosts ?? true, - postsCount: posts.length, - posts, - }); + return NextResponse.json({ success: true, posts }); } export async function POST(request: Request) { try { const payload = await request.json(); - console.log('📥 [WhatsApp Webhook] Mensaje recibido:', JSON.stringify(payload).slice(0, 300)); + console.log('📥 Webhook Evolution API recibido:', JSON.stringify(payload).slice(0, 300)); const data = payload.data || payload; - const settings = dataService.getSettings(); - // 1. Extraer texto del mensaje de WhatsApp const messageContent = data.message?.conversation || data.message?.extendedTextMessage?.text || @@ -31,117 +22,27 @@ export async function POST(request: Request) { data.text || ''; - // 2. Extraer nombre del canal o grupo - const senderPhone = data.key?.remoteJid?.replace(/\D/g, '') || ''; - const isGroup = data.key?.remoteJid?.includes('g.us'); const channelName = - data.groupInfo?.subject || data.pushName || - (isGroup ? 'Grupo Mayorista WhatsApp' : 'Chat Proveedor Directo'); + data.groupInfo?.subject || + (data.key?.remoteJid?.includes('g.us') ? 'Canal Mayorista Entrada' : 'Recepción Directa'); - if (!messageContent || messageContent.trim().length < 6) { - return NextResponse.json({ - success: true, - ignored: 'Mensaje sin texto suficiente para extraer calzado.', - }); + if (!messageContent || messageContent.trim().length < 5) { + return NextResponse.json({ success: true, ignored: 'Mensaje vacío o sin texto relevante' }); } - // 3. Buscar proveedor asociado por teléfono o grupo - const suppliers = dataService.getSuppliers(); - const matchedSupplier = suppliers.find( - (s) => - s.phone.includes(senderPhone) || - (channelName && s.name.toLowerCase().includes(channelName.toLowerCase())) || - (channelName && channelName.toLowerCase().includes(s.name.toLowerCase())) - ); - - const supplierName = matchedSupplier?.name || channelName; - const supplierPhone = matchedSupplier?.phone || senderPhone || '573167455877'; - - // 4. Procesar y extraer información con Gemini AI + // Parsear con Gemini AI const extracted = await parseSupplierMessage(messageContent); - // Recalcular precio con el margen y redondeo al $5.000 oficial - const finalRetailPrice = calculateRetailPrice( - extracted.supplierPrice, - settings.defaultProfitMargin || 35 - ); - - // Extraer imágenes (si Evolution API envió imagen adjunta o usar fotos de alta resolución) - const images: string[] = []; - if (data.message?.imageMessage?.url) { - images.push(data.message.imageMessage.url); - } else { - images.push( - 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80' - ); - } - - // 5. Verificar Anti-Duplicados en el Catálogo - const existingProducts = dataService.getProducts(); - const duplicateProduct = existingProducts.find( - (p) => p.name.toLowerCase() === extracted.name.toLowerCase() - ); - - let registeredProduct: Product | null = null; - const autoPublish = settings.autoPublishSupplierPosts ?? true; - - if (autoPublish) { - if (duplicateProduct) { - // Actualizar stock y tallas existentes sin duplicar - const mergedSizes = Array.from(new Set([...duplicateProduct.sizes, ...extracted.sizes])); - registeredProduct = dataService.updateProduct(duplicateProduct.id, { - supplierPrice: extracted.supplierPrice, - retailPrice: finalRetailPrice, - sizes: mergedSizes, - inStock: true, - isActive: true, - supplierName, - supplierPhone, - }); - console.log(`🔄 [Auto-Sync] Zapatilla "${extracted.name}" actualizada en catálogo (Anti-Duplicados).`); - } else { - // Registrar y publicar automáticamente - registeredProduct = dataService.addProduct({ - name: extracted.name, - brand: extracted.brand, - supplierPrice: extracted.supplierPrice, - retailPrice: finalRetailPrice, - originalPrice: Math.round(finalRetailPrice * 1.35), - sizes: extracted.sizes, - images, - description: `Zapatillas ${extracted.brand} ${extracted.name} garantizadas. Calidad seleccionada con horma nacional y suela antideslizante.`, - category: extracted.category || 'Sneakers / Urbano', - inStock: true, - isActive: true, - isFlashDeal: true, - rating: 4.9, - reviewsCount: 15, - salesCount: 30, - originBadge: 'Bodega Mayorista', - supplierId: matchedSupplier?.id || 'sup-auto', - supplierName, - supplierPhone, - }); - console.log(`✨ [Auto-Publish] Nueva zapatilla "${extracted.name}" publicada automáticamente en tienda.`); - } - } - - // 6. Registrar en el historial de publicaciones recibidas const newPost: SupplierPost = { id: `post-${Date.now()}`, - channelName, - supplierName, - supplierPhone, + channelName: data.groupInfo?.subject || channelName, rawMessage: messageContent, - rawImages: images, - extractedProduct: { - ...extracted, - suggestedRetailPrice: finalRetailPrice, - supplierName, - supplierPhone, - }, - status: autoPublish ? 'published_store' : 'pending_review', + rawImages: [ + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: extracted, + status: 'pending_review', receivedAt: 'Justo ahora', }; @@ -149,12 +50,8 @@ export async function POST(request: Request) { return NextResponse.json({ success: true, - autoPublished: autoPublish, - product: registeredProduct, + message: 'Mensaje procesado con IA e ingresado al feed interno', post: newPost, - message: autoPublish - ? `🔥 ¡Zapatilla "${extracted.name}" procesada y publicada AUTOMÁTICAMENTE en la tienda!` - : `Mensaje ingresado al feed para aprobación manual.`, }); } catch (error: any) { console.error('Error procesando webhook de WhatsApp:', error); diff --git a/sneaky-app/src/lib/data-service.ts b/sneaky-app/src/lib/data-service.ts index db83370..11adc8c 100644 --- a/sneaky-app/src/lib/data-service.ts +++ b/sneaky-app/src/lib/data-service.ts @@ -2138,12 +2138,174 @@ export const INITIAL_MONITORED_GROUPS: MonitoredWhatsAppGroup[] = [ }, ]; +export const INITIAL_ORDERS: Order[] = [ + { + id: 'ORD-8921', + customerName: 'Mateo Valencia', + customerPhone: '3168945120', + address: 'Av 6N # 24N-32 Edificio Granada Real', + cityId: 'city-cali', + cityName: 'Cali (Norte - Granada)', + items: [ + { + productId: 'snk-jordan4-1', + productName: 'Nike Air Jordan 4 Retro White Cement', + brand: 'Jordan', + size: '41', + quantity: 1, + price: 135000, + supplierPrice: 95000, + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + supplierPhone: '573134848203', + image: 'https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 135000, + shippingCost: 0, + totalAmount: 135000, + depositAmount: 10000, + balanceDue: 125000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega Efectivo / Nequi', + status: 'pending', + createdAt: 'Hoy, 06:45 AM', + notes: 'Timbrar en apto 302. Paga con billete de 100 y 50.', + }, + { + id: 'ORD-8922', + customerName: 'Valentina Restrepo', + customerPhone: '3157829401', + address: 'Calle 52N # 4BN-15 Casa 4 La Flora', + cityId: 'city-cali', + cityName: 'Cali (Norte - La Flora)', + items: [ + { + productId: 'snk-vomero5-1', + productName: 'Nike Zoom Vomero 5 Photon Dust Metallic Silver', + brand: 'Nike', + size: '39', + quantity: 1, + price: 130000, + supplierPrice: 90000, + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + supplierPhone: '573134848203', + image: 'https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 130000, + shippingCost: 0, + totalAmount: 130000, + depositAmount: 10000, + balanceDue: 120000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega Nequi', + status: 'pending', + createdAt: 'Hoy, 07:15 AM', + notes: 'Dejar en portería si no contesta.', + }, + { + id: 'ORD-8923', + customerName: 'Santiago Henao', + customerPhone: '3186523910', + address: 'Cra 105 # 14-45 Condominio Portal de la Viga', + cityId: 'city-cali', + cityName: 'Cali (Sur - Ciudad Jardín)', + items: [ + { + productId: 'snk-campus-1', + productName: 'Adidas Campus 00s Core Black White', + brand: 'Adidas', + size: '40', + quantity: 1, + price: 125000, + supplierPrice: 85000, + supplierName: 'EXCLUSIVE CC MÍO 3B', + supplierPhone: '573159876543', + image: 'https://images.unsplash.com/photo-1525966222134-fcfa99b8ae77?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 125000, + shippingCost: 0, + totalAmount: 125000, + depositAmount: 10000, + balanceDue: 115000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega', + status: 'pending', + createdAt: 'Hoy, 07:30 AM', + notes: 'Recibe en horas de la tarde después de las 2 PM.', + }, + { + id: 'ORD-8924', + customerName: 'Camila Ospina', + customerPhone: '3114958203', + address: 'Cra 85E # 14-80 Apto 501 El Ingenio', + cityId: 'city-cali', + cityName: 'Cali (Sur - El Ingenio)', + items: [ + { + productId: 'snk-coach-1', + productName: 'Coach Low Top Monogram Signature Brown', + brand: 'Coach', + size: '38', + quantity: 1, + price: 145000, + supplierPrice: 100000, + supplierName: 'EXCLUSIVE CC MÍO 3B', + supplierPhone: '573159876543', + image: 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 145000, + shippingCost: 0, + totalAmount: 145000, + depositAmount: 10000, + balanceDue: 135000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Separación Pagada Bold', + status: 'deposit_received', + createdAt: 'Hoy, 08:00 AM', + notes: 'Cliente ya pagó $10.000 de anticipo.', + }, + { + id: 'ORD-8925', + customerName: 'Daniel Caicedo', + customerPhone: '3174829105', + address: 'Cra 10 # 3-45 San Antonio', + cityId: 'city-cali', + cityName: 'Cali (Oeste - San Antonio)', + items: [ + { + productId: 'snk-af1-1', + productName: 'Nike Air Force 1 07 Low Triple White', + brand: 'Nike', + size: '42', + quantity: 1, + price: 120000, + supplierPrice: 80000, + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + supplierPhone: '573134848203', + image: 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 120000, + shippingCost: 0, + totalAmount: 120000, + depositAmount: 10000, + balanceDue: 110000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega', + status: 'pending', + createdAt: 'Hoy, 08:20 AM', + }, +]; + class DataService { private products: Product[] = [...INITIAL_PRODUCTS]; private cities: City[] = [...INITIAL_CITIES]; private paymentMethods: PaymentMethod[] = [...INITIAL_PAYMENT_METHODS]; private suppliers: Supplier[] = [...INITIAL_SUPPLIERS]; - private orders: Order[] = []; + private orders: Order[] = [...INITIAL_ORDERS]; private supplierPosts: SupplierPost[] = [...INITIAL_SUPPLIER_POSTS]; getProducts(): Product[] { @@ -2225,6 +2387,30 @@ class DataService { return order; } + createOrder(orderData: Partial): Order { + const newOrder: Order = { + id: `ord-${Date.now()}`, + customerName: orderData.customerName || 'Cliente', + customerPhone: orderData.customerPhone || '', + address: orderData.address || '', + cityId: orderData.cityId || 'city-cali', + cityName: orderData.cityName || 'Cali', + items: orderData.items || [], + subtotal: orderData.subtotal || 0, + shippingCost: orderData.shippingCost || 0, + totalAmount: orderData.totalAmount || 0, + depositAmount: orderData.depositAmount || 10000, + balanceDue: (orderData.totalAmount || 0) - (orderData.depositAmount || 10000), + paymentMethodId: orderData.paymentMethodId || 'pay-contraentrega', + paymentMethodName: orderData.paymentMethodName || 'Contraentrega', + status: 'pending', + notes: orderData.notes, + createdAt: new Date().toISOString(), + }; + this.orders.unshift(newOrder); + return newOrder; + } + updateOrderStatus(orderId: string, status: Order['status']): Order | null { const order = this.orders.find((o) => o.id === orderId); if (!order) return null; @@ -2243,12 +2429,12 @@ class DataService { // Configuración de la Tienda private settings: StoreSettings = { - storeName: 'Sneaky Drops', - slogan: 'Viral Sneakers & Exclusivos', + storeName: 'DripZone', + slogan: 'Luxury Streetwear & Collectibles', email: 'carlos.andres.lasso@gmail.com', phone: '3167455877', whatsappNumber: '573167455877', - instagramHandle: '@sneakydrops.co', + instagramHandle: '@dripzone.co', address: 'Bodega Central / Cali', city: 'Cali, Colombia', nequiAccount: '316 745 5877', @@ -2290,7 +2476,7 @@ class DataService { { id: 'usr-operator-1', name: 'Andrés Operador Despachos', - email: 'despachos@sneakydrops.co', + email: 'despachos@dripzone.co', phone: '3159876543', city: 'Cali', role: 'operator', @@ -2364,7 +2550,6 @@ class DataService { } return null; } - } export const dataService = new DataService(); diff --git a/zapply-app/src/lib/data-service.ts b/zapply-app/src/lib/data-service.ts index ea2c8f0..11adc8c 100644 --- a/zapply-app/src/lib/data-service.ts +++ b/zapply-app/src/lib/data-service.ts @@ -2138,12 +2138,174 @@ export const INITIAL_MONITORED_GROUPS: MonitoredWhatsAppGroup[] = [ }, ]; +export const INITIAL_ORDERS: Order[] = [ + { + id: 'ORD-8921', + customerName: 'Mateo Valencia', + customerPhone: '3168945120', + address: 'Av 6N # 24N-32 Edificio Granada Real', + cityId: 'city-cali', + cityName: 'Cali (Norte - Granada)', + items: [ + { + productId: 'snk-jordan4-1', + productName: 'Nike Air Jordan 4 Retro White Cement', + brand: 'Jordan', + size: '41', + quantity: 1, + price: 135000, + supplierPrice: 95000, + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + supplierPhone: '573134848203', + image: 'https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 135000, + shippingCost: 0, + totalAmount: 135000, + depositAmount: 10000, + balanceDue: 125000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega Efectivo / Nequi', + status: 'pending', + createdAt: 'Hoy, 06:45 AM', + notes: 'Timbrar en apto 302. Paga con billete de 100 y 50.', + }, + { + id: 'ORD-8922', + customerName: 'Valentina Restrepo', + customerPhone: '3157829401', + address: 'Calle 52N # 4BN-15 Casa 4 La Flora', + cityId: 'city-cali', + cityName: 'Cali (Norte - La Flora)', + items: [ + { + productId: 'snk-vomero5-1', + productName: 'Nike Zoom Vomero 5 Photon Dust Metallic Silver', + brand: 'Nike', + size: '39', + quantity: 1, + price: 130000, + supplierPrice: 90000, + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + supplierPhone: '573134848203', + image: 'https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 130000, + shippingCost: 0, + totalAmount: 130000, + depositAmount: 10000, + balanceDue: 120000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega Nequi', + status: 'pending', + createdAt: 'Hoy, 07:15 AM', + notes: 'Dejar en portería si no contesta.', + }, + { + id: 'ORD-8923', + customerName: 'Santiago Henao', + customerPhone: '3186523910', + address: 'Cra 105 # 14-45 Condominio Portal de la Viga', + cityId: 'city-cali', + cityName: 'Cali (Sur - Ciudad Jardín)', + items: [ + { + productId: 'snk-campus-1', + productName: 'Adidas Campus 00s Core Black White', + brand: 'Adidas', + size: '40', + quantity: 1, + price: 125000, + supplierPrice: 85000, + supplierName: 'EXCLUSIVE CC MÍO 3B', + supplierPhone: '573159876543', + image: 'https://images.unsplash.com/photo-1525966222134-fcfa99b8ae77?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 125000, + shippingCost: 0, + totalAmount: 125000, + depositAmount: 10000, + balanceDue: 115000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega', + status: 'pending', + createdAt: 'Hoy, 07:30 AM', + notes: 'Recibe en horas de la tarde después de las 2 PM.', + }, + { + id: 'ORD-8924', + customerName: 'Camila Ospina', + customerPhone: '3114958203', + address: 'Cra 85E # 14-80 Apto 501 El Ingenio', + cityId: 'city-cali', + cityName: 'Cali (Sur - El Ingenio)', + items: [ + { + productId: 'snk-coach-1', + productName: 'Coach Low Top Monogram Signature Brown', + brand: 'Coach', + size: '38', + quantity: 1, + price: 145000, + supplierPrice: 100000, + supplierName: 'EXCLUSIVE CC MÍO 3B', + supplierPhone: '573159876543', + image: 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 145000, + shippingCost: 0, + totalAmount: 145000, + depositAmount: 10000, + balanceDue: 135000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Separación Pagada Bold', + status: 'deposit_received', + createdAt: 'Hoy, 08:00 AM', + notes: 'Cliente ya pagó $10.000 de anticipo.', + }, + { + id: 'ORD-8925', + customerName: 'Daniel Caicedo', + customerPhone: '3174829105', + address: 'Cra 10 # 3-45 San Antonio', + cityId: 'city-cali', + cityName: 'Cali (Oeste - San Antonio)', + items: [ + { + productId: 'snk-af1-1', + productName: 'Nike Air Force 1 07 Low Triple White', + brand: 'Nike', + size: '42', + quantity: 1, + price: 120000, + supplierPrice: 80000, + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + supplierPhone: '573134848203', + image: 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + }, + ], + subtotal: 120000, + shippingCost: 0, + totalAmount: 120000, + depositAmount: 10000, + balanceDue: 110000, + paymentMethodId: 'pay-contraentrega', + paymentMethodName: 'Contraentrega', + status: 'pending', + createdAt: 'Hoy, 08:20 AM', + }, +]; + class DataService { private products: Product[] = [...INITIAL_PRODUCTS]; private cities: City[] = [...INITIAL_CITIES]; private paymentMethods: PaymentMethod[] = [...INITIAL_PAYMENT_METHODS]; private suppliers: Supplier[] = [...INITIAL_SUPPLIERS]; - private orders: Order[] = []; + private orders: Order[] = [...INITIAL_ORDERS]; private supplierPosts: SupplierPost[] = [...INITIAL_SUPPLIER_POSTS]; getProducts(): Product[] { @@ -2225,6 +2387,30 @@ class DataService { return order; } + createOrder(orderData: Partial): Order { + const newOrder: Order = { + id: `ord-${Date.now()}`, + customerName: orderData.customerName || 'Cliente', + customerPhone: orderData.customerPhone || '', + address: orderData.address || '', + cityId: orderData.cityId || 'city-cali', + cityName: orderData.cityName || 'Cali', + items: orderData.items || [], + subtotal: orderData.subtotal || 0, + shippingCost: orderData.shippingCost || 0, + totalAmount: orderData.totalAmount || 0, + depositAmount: orderData.depositAmount || 10000, + balanceDue: (orderData.totalAmount || 0) - (orderData.depositAmount || 10000), + paymentMethodId: orderData.paymentMethodId || 'pay-contraentrega', + paymentMethodName: orderData.paymentMethodName || 'Contraentrega', + status: 'pending', + notes: orderData.notes, + createdAt: new Date().toISOString(), + }; + this.orders.unshift(newOrder); + return newOrder; + } + updateOrderStatus(orderId: string, status: Order['status']): Order | null { const order = this.orders.find((o) => o.id === orderId); if (!order) return null; @@ -2243,12 +2429,12 @@ class DataService { // Configuración de la Tienda private settings: StoreSettings = { - storeName: 'Zapply Cali', - slogan: 'Sneakers Express • Entregas en 24 Horas', + storeName: 'DripZone', + slogan: 'Luxury Streetwear & Collectibles', email: 'carlos.andres.lasso@gmail.com', phone: '3167455877', whatsappNumber: '573167455877', - instagramHandle: '@zapplycali.co', + instagramHandle: '@dripzone.co', address: 'Bodega Central / Cali', city: 'Cali, Colombia', nequiAccount: '316 745 5877', @@ -2290,7 +2476,7 @@ class DataService { { id: 'usr-operator-1', name: 'Andrés Operador Despachos', - email: 'despachos@zapply.co', + email: 'despachos@dripzone.co', phone: '3159876543', city: 'Cali', role: 'operator', @@ -2364,7 +2550,6 @@ class DataService { } return null; } - } export const dataService = new DataService();