728 lines
22 KiB
TypeScript
728 lines
22 KiB
TypeScript
import { Product, City, PaymentMethod, Order, SupplierPost, StoreSettings, Supplier, MonitoredWhatsAppGroup, User } from '@/types';
|
||
|
||
export const INITIAL_SUPPLIERS: Supplier[] = [
|
||
{
|
||
"id": "sup-jovic",
|
||
"name": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀",
|
||
"phone": "573167455877",
|
||
"contactPerson": "Asesor Jovic Store",
|
||
"address": "Centro / Bodega Cali",
|
||
"notes": "Proveedor oficial Nike, Jordan, Nocta y Vomero calidades Top.",
|
||
"isActive": true
|
||
},
|
||
{
|
||
"id": "sup-ccmio",
|
||
"name": "EXCLUSIVE CC MÍO 3B",
|
||
"phone": "573159876543",
|
||
"contactPerson": "Despachos CC MÍO 3B",
|
||
"address": "CC MÍO Local 3B, Cali",
|
||
"notes": "Especialista en Adidas, Coach, Timberland y Skatewear.",
|
||
"isActive": true
|
||
},
|
||
{
|
||
"id": "sup-central",
|
||
"name": "BODEGA CENTRAL MAYORISTA",
|
||
"phone": "573101234567",
|
||
"contactPerson": "Logística Despachos",
|
||
"address": "San Andresito / Cali",
|
||
"notes": "Despacho rápido en 24 horas para separación inmediata.",
|
||
"isActive": true
|
||
}
|
||
];
|
||
|
||
export const INITIAL_CITIES: City[] = [
|
||
{
|
||
id: 'city-cali',
|
||
name: 'Cali',
|
||
department: 'Valle del Cauca',
|
||
shippingCost: 0,
|
||
deliveryTime: 'Entrega en 24 Horas (Domicilio Local)',
|
||
allowsContraentrega: true,
|
||
firstExchangeFree: true,
|
||
exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Cali (posteriores con flete estándar)',
|
||
},
|
||
{
|
||
id: 'city-jamundi',
|
||
name: 'Jamundí',
|
||
department: 'Valle del Cauca',
|
||
shippingCost: 5000,
|
||
deliveryTime: 'Entrega en 24 Horas',
|
||
allowsContraentrega: true,
|
||
firstExchangeFree: true,
|
||
exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Jamundí (posteriores con flete estándar)',
|
||
},
|
||
{
|
||
id: 'city-palmira',
|
||
name: 'Palmira',
|
||
department: 'Valle del Cauca',
|
||
shippingCost: 7000,
|
||
deliveryTime: 'Entrega en 24 Horas',
|
||
allowsContraentrega: true,
|
||
firstExchangeFree: true,
|
||
exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Palmira (posteriores con flete estándar)',
|
||
},
|
||
{
|
||
id: 'city-yumbo',
|
||
name: 'Yumbo',
|
||
department: 'Valle del Cauca',
|
||
shippingCost: 5000,
|
||
deliveryTime: 'Entrega en 24 Horas',
|
||
allowsContraentrega: true,
|
||
firstExchangeFree: true,
|
||
exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Yumbo (posteriores con flete estándar)',
|
||
},
|
||
{
|
||
id: 'city-bogota',
|
||
name: 'Bogotá D.C.',
|
||
department: 'Cundinamarca',
|
||
shippingCost: 12000,
|
||
deliveryTime: '2 a 3 días hábiles',
|
||
allowsContraentrega: true,
|
||
firstExchangeFree: false,
|
||
exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)',
|
||
},
|
||
{
|
||
id: 'city-medellin',
|
||
name: 'Medellín',
|
||
department: 'Antioquia',
|
||
shippingCost: 12000,
|
||
deliveryTime: '2 a 3 días hábiles',
|
||
allowsContraentrega: true,
|
||
firstExchangeFree: false,
|
||
exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)',
|
||
},
|
||
{
|
||
id: 'city-barranquilla',
|
||
name: 'Barranquilla',
|
||
department: 'Atlántico',
|
||
shippingCost: 14000,
|
||
deliveryTime: '3 a 4 días hábiles',
|
||
allowsContraentrega: true,
|
||
firstExchangeFree: false,
|
||
exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)',
|
||
},
|
||
{
|
||
id: 'city-nacional',
|
||
name: 'Otras Ciudades / Resto del País',
|
||
department: 'Colombia',
|
||
shippingCost: 15000,
|
||
deliveryTime: '2 a 5 días hábiles',
|
||
allowsContraentrega: false,
|
||
firstExchangeFree: false,
|
||
exchangePolicyNote: 'Cambio de talla garantizado (flete nacional asumido por el cliente)',
|
||
},
|
||
];
|
||
|
||
// Métodos de Pago configurables por el Admin
|
||
export const INITIAL_PAYMENT_METHODS: PaymentMethod[] = [
|
||
{
|
||
id: 'pay-bold-link',
|
||
name: 'Bold.co • PSE, Tarjetas Débito/Crédito, Nequi o QR (Oficial)',
|
||
type: 'bold',
|
||
description: 'Paga de forma rápida y 100% segura con tu cuenta Bold. Acepta PSE, Tarjetas Visa/Mastercard y QR de cualquier banco.',
|
||
requiresDeposit: false,
|
||
depositAmount: 0,
|
||
boldPaymentLink: 'https://bold.co/p/carlos-lasso',
|
||
accountInfo: 'Pasarela Oficial Bold.co • PSE / Tarjetas / QR',
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 'pay-deposit-10k',
|
||
name: 'Separación con $10.000 + Saldo Contraentrega',
|
||
type: 'contraentrega',
|
||
description: 'Asegura tu talla con solo $10.000 COP vía Bold/Nequi/Daviplata y cancelas el saldo restante en efectivo o transferencia cuando el mensajero llegue a tu casa.',
|
||
requiresDeposit: true,
|
||
depositAmount: 10000,
|
||
accountInfo: 'Nequi / Daviplata Oficial: 316 745 5877 (Carlos Andrés Lasso)',
|
||
boldPaymentLink: 'https://bold.co/p/carlos-lasso',
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 'pay-cod-full',
|
||
name: 'Pago 100% Contraentrega (Cali y Alrededores)',
|
||
type: 'contraentrega',
|
||
description: 'Pagas el 100% del valor total al recibir en tu puerta (válido para entregas urbanas en 24 horas).',
|
||
requiresDeposit: false,
|
||
depositAmount: 0,
|
||
isActive: true,
|
||
},
|
||
{
|
||
id: 'pay-nequi-full',
|
||
name: 'Transferencia Total Anticipada Nequi / Daviplata',
|
||
type: 'nequi',
|
||
description: 'Paga el 100% anticipado y recibe prioridad de despacho express en 24 horas.',
|
||
requiresDeposit: false,
|
||
depositAmount: 0,
|
||
accountInfo: 'Nequi / Daviplata: 316 745 5877 (Carlos Andrés Lasso)',
|
||
isActive: true,
|
||
},
|
||
];
|
||
|
||
export const INITIAL_PRODUCTS: Product[] = [];
|
||
|
||
export const INITIAL_SUPPLIER_POSTS: SupplierPost[] = [
|
||
{
|
||
id: 'post-1',
|
||
channelName: 'DIFUSION JOVIC STORE',
|
||
supplierName: 'DIFUSION JOVIC STORE',
|
||
supplierPhone: '573134848203',
|
||
rawMessage: `🔥 DISPONIBLE HOY 🔥\nNike Air Force 1 All White\nTallas: 37 al 43\nMayorista: $90.000 c/u\nDespacho inmediato Cali`,
|
||
rawImages: [
|
||
'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80',
|
||
],
|
||
extractedProduct: {
|
||
name: 'Nike Air Force 1 Low 07 White Triple',
|
||
brand: 'Nike',
|
||
sizes: ['37', '38', '39', '40', '41', '42', '43'],
|
||
supplierPrice: 90000,
|
||
suggestedRetailPrice: 125000,
|
||
category: 'Sneakers / Urbano',
|
||
confidence: 0.96,
|
||
supplierName: 'DIFUSION JOVIC STORE',
|
||
supplierPhone: '573134848203',
|
||
},
|
||
status: 'published_store',
|
||
receivedAt: 'Hoy, 09:15 AM',
|
||
},
|
||
{
|
||
id: 'post-2',
|
||
channelName: 'EXCLUSIVE CC MIO 3B',
|
||
supplierName: 'EXCLUSIVE CC MIO 3B',
|
||
supplierPhone: '573159876543',
|
||
rawMessage: `👟 JORDAN 4 MILITARY BLACK 👟\nFull calidad AAA, caja original\nTallas 38 a 43\nPrecio: $95.000\nDomicilio pago contraentrega`,
|
||
rawImages: [
|
||
'https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80',
|
||
],
|
||
extractedProduct: {
|
||
name: 'Air Jordan 4 Retro Military Black',
|
||
brand: 'Jordan',
|
||
sizes: ['38', '39', '40', '41', '42', '43'],
|
||
supplierPrice: 95000,
|
||
suggestedRetailPrice: 130000,
|
||
category: 'Sneakers / Colección',
|
||
confidence: 0.94,
|
||
supplierName: 'EXCLUSIVE CC MIO 3B',
|
||
supplierPhone: '573159876543',
|
||
},
|
||
status: 'published_store',
|
||
receivedAt: 'Hoy, 10:40 AM',
|
||
},
|
||
];
|
||
|
||
|
||
export const INITIAL_MONITORED_GROUPS: MonitoredWhatsAppGroup[] = [
|
||
{
|
||
id: 'grp-jovic',
|
||
jid: '120363049363072784@g.us',
|
||
name: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀',
|
||
isMonitored: true,
|
||
supplierId: 'sup-jovic',
|
||
supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀',
|
||
profitMarginOverride: 35,
|
||
autoPublish: true,
|
||
participantsCount: 450,
|
||
notes: 'Proveedor oficial Nike, Jordan, Vomero, Nocta y AF1.',
|
||
},
|
||
{
|
||
id: 'grp-ccmio',
|
||
jid: '120363024823901923@g.us',
|
||
name: 'EXCLUSIVE CC MÍO 3B',
|
||
isMonitored: true,
|
||
supplierId: 'sup-ccmio',
|
||
supplierName: 'EXCLUSIVE CC MÍO 3B',
|
||
profitMarginOverride: 35,
|
||
autoPublish: true,
|
||
participantsCount: 380,
|
||
notes: 'Proveedor oficial Adidas, Coach, Timberland y Skatewear.',
|
||
},
|
||
];
|
||
|
||
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[] = [...INITIAL_ORDERS];
|
||
private supplierPosts: SupplierPost[] = [...INITIAL_SUPPLIER_POSTS];
|
||
|
||
getProducts(): Product[] {
|
||
return this.products;
|
||
}
|
||
|
||
getProductById(id: string): Product | undefined {
|
||
return this.products.find((p) => p.id === id);
|
||
}
|
||
|
||
addProduct(product: Product): Product {
|
||
this.products.unshift(product);
|
||
return product;
|
||
}
|
||
|
||
updateProduct(id: string, updates: Partial<Product>): Product | null {
|
||
const idx = this.products.findIndex((p) => p.id === id);
|
||
if (idx === -1) return null;
|
||
this.products[idx] = { ...this.products[idx], ...updates };
|
||
return this.products[idx];
|
||
}
|
||
|
||
deleteProduct(id: string): boolean {
|
||
const initialLen = this.products.length;
|
||
this.products = this.products.filter((p) => p.id !== id);
|
||
return this.products.length < initialLen;
|
||
}
|
||
|
||
getSuppliers(includeInactive: boolean = true): Supplier[] {
|
||
if (includeInactive) return this.suppliers;
|
||
return this.suppliers.filter((s) => s.isActive !== false);
|
||
}
|
||
|
||
getSupplierById(id: string): Supplier | undefined {
|
||
return this.suppliers.find((s) => s.id === id);
|
||
}
|
||
|
||
addSupplier(supplier: Partial<Supplier>): Supplier {
|
||
const newSupplier: Supplier = {
|
||
id: supplier.id || `sup-${Date.now()}`,
|
||
name: supplier.name || 'Nuevo Proveedor',
|
||
phone: supplier.phone || '573167455877',
|
||
contactPerson: supplier.contactPerson || '',
|
||
address: supplier.address || '',
|
||
notes: supplier.notes || '',
|
||
isActive: supplier.isActive !== undefined ? supplier.isActive : true,
|
||
};
|
||
this.suppliers.push(newSupplier);
|
||
return newSupplier;
|
||
}
|
||
|
||
updateSupplier(id: string, updates: Partial<Supplier>): Supplier | null {
|
||
const idx = this.suppliers.findIndex((s) => s.id === id);
|
||
if (idx === -1) return null;
|
||
this.suppliers[idx] = { ...this.suppliers[idx], ...updates };
|
||
return this.suppliers[idx];
|
||
}
|
||
|
||
deleteSupplier(id: string): boolean {
|
||
// Soft delete (desactivación segura para preservar 100% el historial de pedidos y productos)
|
||
const supplier = this.suppliers.find((s) => s.id === id);
|
||
if (!supplier) return false;
|
||
supplier.isActive = false;
|
||
return true;
|
||
}
|
||
|
||
getCities(): City[] {
|
||
return this.cities;
|
||
}
|
||
|
||
getCityById(id: string): City | undefined {
|
||
return this.cities.find((c) => c.id === id);
|
||
}
|
||
|
||
addCity(city: City): City {
|
||
this.cities.push(city);
|
||
return city;
|
||
}
|
||
|
||
updateCity(id: string, updates: Partial<City>): City | null {
|
||
const idx = this.cities.findIndex((c) => c.id === id);
|
||
if (idx === -1) return null;
|
||
this.cities[idx] = { ...this.cities[idx], ...updates };
|
||
return this.cities[idx];
|
||
}
|
||
|
||
getPaymentMethods(): PaymentMethod[] {
|
||
return this.paymentMethods;
|
||
}
|
||
|
||
updatePaymentMethod(id: string, updates: Partial<PaymentMethod>): PaymentMethod | null {
|
||
const idx = this.paymentMethods.findIndex((p) => p.id === id);
|
||
if (idx === -1) return null;
|
||
this.paymentMethods[idx] = { ...this.paymentMethods[idx], ...updates };
|
||
return this.paymentMethods[idx];
|
||
}
|
||
|
||
getOrders(): Order[] {
|
||
return this.orders;
|
||
}
|
||
|
||
getOrderById(id: string): Order | undefined {
|
||
return this.orders.find((o) => o.id === id);
|
||
}
|
||
|
||
addOrder(order: Order): Order {
|
||
this.orders.unshift(order);
|
||
return order;
|
||
}
|
||
|
||
createOrder(orderData: Partial<Order>): Order {
|
||
const newOrder: Order = {
|
||
id: orderData.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 !== undefined ? orderData.depositAmount : 10000,
|
||
balanceDue: orderData.balanceDue !== undefined ? orderData.balanceDue : ((orderData.totalAmount || 0) - (orderData.depositAmount !== undefined ? orderData.depositAmount : 10000)),
|
||
paymentMethodId: orderData.paymentMethodId || 'pay-contraentrega',
|
||
paymentMethodName: orderData.paymentMethodName || 'Contraentrega',
|
||
status: orderData.status || 'pending',
|
||
notes: orderData.notes,
|
||
createdAt: orderData.createdAt || new Date().toISOString(),
|
||
};
|
||
this.orders.unshift(newOrder);
|
||
return newOrder;
|
||
}
|
||
|
||
updateOrder(id: string, updates: Partial<Order>): Order | null {
|
||
const idx = this.orders.findIndex((o) => o.id === id);
|
||
if (idx === -1) return null;
|
||
|
||
const current = this.orders[idx];
|
||
const total = updates.totalAmount !== undefined ? updates.totalAmount : current.totalAmount;
|
||
const deposit = updates.depositAmount !== undefined ? updates.depositAmount : current.depositAmount;
|
||
const balanceDue = updates.balanceDue !== undefined ? updates.balanceDue : (total - deposit);
|
||
|
||
this.orders[idx] = {
|
||
...current,
|
||
...updates,
|
||
totalAmount: total,
|
||
depositAmount: deposit,
|
||
balanceDue,
|
||
};
|
||
return this.orders[idx];
|
||
}
|
||
|
||
deleteOrder(id: string): boolean {
|
||
const initialLen = this.orders.length;
|
||
this.orders = this.orders.filter((o) => o.id !== id);
|
||
return this.orders.length < initialLen;
|
||
}
|
||
|
||
updateOrderStatus(orderId: string, status: Order['status']): Order | null {
|
||
const order = this.orders.find((o) => o.id === orderId);
|
||
if (!order) return null;
|
||
order.status = status;
|
||
return order;
|
||
}
|
||
|
||
getSupplierPosts(): SupplierPost[] {
|
||
return this.supplierPosts;
|
||
}
|
||
|
||
addSupplierPost(post: SupplierPost): SupplierPost {
|
||
this.supplierPosts.unshift(post);
|
||
return post;
|
||
}
|
||
|
||
saveSupplierPosts(posts: SupplierPost[]): SupplierPost[] {
|
||
posts.forEach((newP) => {
|
||
const exists = this.supplierPosts.some(
|
||
(p) => p.id === newP.id || (p.rawMessage && p.rawMessage === newP.rawMessage && (p as any).channelJid === (newP as any).channelJid)
|
||
);
|
||
if (!exists) {
|
||
this.supplierPosts.unshift(newP);
|
||
}
|
||
});
|
||
return this.supplierPosts;
|
||
}
|
||
|
||
updateSupplierPostStatus(id: string, status: SupplierPost['status']): boolean {
|
||
const post = this.supplierPosts.find((p) => p.id === id);
|
||
if (!post) return false;
|
||
post.status = status;
|
||
return true;
|
||
}
|
||
|
||
// Configuración de la Tienda
|
||
private settings: StoreSettings = {
|
||
storeName: 'DripZone',
|
||
slogan: 'Luxury Streetwear & Collectibles',
|
||
email: 'carlos.andres.lasso@gmail.com',
|
||
phone: '3167455877',
|
||
whatsappNumber: '573167455877',
|
||
instagramHandle: '@dripzone.co',
|
||
address: 'Bodega Central / Cali',
|
||
city: 'Cali, Colombia',
|
||
nequiAccount: '316 745 5877',
|
||
daviplataAccount: '316 745 5877',
|
||
accountHolder: 'Carlos Andrés Lasso',
|
||
boldPaymentLink: 'https://bold.co/p/carlos-lasso',
|
||
boldApiKey: '',
|
||
boldMerchantId: '',
|
||
boldQrUrl: '',
|
||
boldEnabled: true,
|
||
defaultProfitMargin: 35,
|
||
defaultDepositAmount: 10000,
|
||
};
|
||
|
||
getSettings(): StoreSettings {
|
||
return this.settings;
|
||
}
|
||
|
||
updateSettings(updates: Partial<StoreSettings>): StoreSettings {
|
||
this.settings = { ...this.settings, ...updates };
|
||
return this.settings;
|
||
}
|
||
|
||
// Control de Usuarios
|
||
private users: User[] = [
|
||
{
|
||
id: 'usr-admin-1',
|
||
name: 'Carlos Andrés Lasso',
|
||
email: 'carlos.andres.lasso@gmail.com',
|
||
phone: '3167455877',
|
||
city: 'Cali',
|
||
address: 'Centro / Bodega Principal',
|
||
role: 'admin',
|
||
isActive: true,
|
||
createdAt: '2026-01-10',
|
||
totalOrders: 0,
|
||
lastLogin: 'Hoy, 08:15 PM',
|
||
},
|
||
{
|
||
id: 'usr-operator-1',
|
||
name: 'Andrés Operador Despachos',
|
||
email: 'despachos@dripzone.co',
|
||
phone: '3159876543',
|
||
city: 'Cali',
|
||
role: 'operator',
|
||
isActive: true,
|
||
createdAt: '2026-02-01',
|
||
totalOrders: 0,
|
||
lastLogin: 'Hoy, 05:30 PM',
|
||
},
|
||
{
|
||
id: 'usr-cust-1',
|
||
name: 'Mateo Gómez (Cliente VIP)',
|
||
email: 'mateo.sneakers@gmail.com',
|
||
phone: '3112345678',
|
||
city: 'Cali',
|
||
address: 'Calle 5 # 34-12 Apto 402',
|
||
role: 'customer',
|
||
isActive: true,
|
||
createdAt: '2026-02-15',
|
||
totalOrders: 3,
|
||
lastLogin: 'Ayer, 08:20 PM',
|
||
},
|
||
];
|
||
|
||
getUsers(): User[] {
|
||
return this.users;
|
||
}
|
||
|
||
addUser(user: User): User {
|
||
this.users.unshift(user);
|
||
return user;
|
||
}
|
||
|
||
updateUser(id: string, updates: Partial<User>): User | null {
|
||
const idx = this.users.findIndex((u) => u.id === id);
|
||
if (idx === -1) return null;
|
||
this.users[idx] = { ...this.users[idx], ...updates };
|
||
return this.users[idx];
|
||
}
|
||
|
||
deleteUser(id: string): boolean {
|
||
const idx = this.users.findIndex((u) => u.id === id);
|
||
if (idx === -1) return false;
|
||
this.users.splice(idx, 1);
|
||
return true;
|
||
}
|
||
|
||
authenticate(emailOrPhone: string): User | null {
|
||
const q = emailOrPhone.trim().toLowerCase();
|
||
const user = this.users.find(
|
||
(u) => u.email.toLowerCase() === q || u.phone === q || u.phone.includes(q)
|
||
);
|
||
return user || null;
|
||
}
|
||
|
||
private monitoredGroups: MonitoredWhatsAppGroup[] = [...INITIAL_MONITORED_GROUPS];
|
||
|
||
getMonitoredGroups(): MonitoredWhatsAppGroup[] {
|
||
return this.monitoredGroups;
|
||
}
|
||
|
||
saveMonitoredGroups(groups: MonitoredWhatsAppGroup[]): MonitoredWhatsAppGroup[] {
|
||
this.monitoredGroups = groups;
|
||
return this.monitoredGroups;
|
||
}
|
||
|
||
toggleGroupMonitoring(idOrJid: string, isMonitored: boolean): MonitoredWhatsAppGroup | null {
|
||
const grp = this.monitoredGroups.find((g) => g.id === idOrJid || g.jid === idOrJid);
|
||
if (grp) {
|
||
grp.isMonitored = isMonitored;
|
||
return grp;
|
||
}
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export const dataService = new DataService();
|