File size: 10,675 Bytes
b44ef76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
import os
import time
import platform
import psutil
import socket
import requests
import pandas as pd
from pytrends.request import TrendReq
from dotenv import load_dotenv

# --------------------------
# CONFIGURA TU PRODUCTO AQUÍ (SOLO CAMBIA ESTO)
# --------------------------
NOMBRE_PRODUCTO = "Funda de silicona para iPhone 16"  # Lo que vendes
PALABRA_CLAVE_BUSQUEDA = "silicone case iPhone 16"    # Cómo lo busca la gente en EE.UU.
COSTO_TU_PRODUCTO_MXN = 85.0                          # Cuánto te cuesta a ti (MXN)
PESO_PRODUCTO_GRAMOS = 120                            # Peso con empaque (g)
PRECIO_VENTA_OBJETIVO_USD = 19.99                     # Precio que quieres cobrar (USD)
EBAY_CLIENT_ID = "TU_CLIENT_ID_AQUI"                  # Client ID de eBay (opcional)
# --------------------------

load_dotenv()
EBAY_CLIENT_ID = os.getenv("EBAY_CLIENT_ID", EBAY_CLIENT_ID)
TIPO_CAMBIO_USD_MXN = 17.20  # Actualiza si cambia (USD → MXN)

# ==================================================
# NUEVA SECCIÓN: VERIFICACIÓN DEL DISPOSITIVO REAL (TÚ EQUIPO)
# ✅ Sin ubicación ✅ Sin datos personales ✅ Todo local
# ==================================================
def verificar_dispositivo_local() -> dict:
    """
    Detecta SOLO el equipo donde se ejecuta el código (anónimo):
    - Sistema operativo + versión
    - CPU, núcleos, RAM total
    - Espacio en disco libre
    - Versión de Python instalada
    - Hostname local (solo nombre de tu equipo en tu red, nada público)
    NO LEE: IP pública, ubicación, GPS, archivos, cuentas, nada personal.
    """
    try:
        # Sistema operativo
        so = f"{platform.system()} {platform.release()} ({platform.version()})"
        arquitectura = platform.machine()
        
        # CPU
        cpu_nombre = platform.processor() or "CPU genérico"
        cpu_nucleos = psutil.cpu_count(logical=True)
        cpu_uso_actual = psutil.cpu_percent(interval=0.5)
        
        # RAM
        ram_total_gb = round(psutil.virtual_memory().total / (1024**3), 1)
        ram_libre_gb = round(psutil.virtual_memory().available / (1024**3), 1)
        
        # Disco (unidad principal)
        disco = psutil.disk_usage(os.path.abspath(os.sep))
        disco_total_gb = round(disco.total / (1024**3), 1)
        disco_libre_gb = round(disco.free / (1024**3), 1)
        
        # Python
        python_version = platform.python_version()
        
        # Nombre local del equipo (solo en tu red, no sale a internet)
        nombre_equipo = socket.gethostname()
        
        # Verificar si es un equipo físico válido (no entorno de prueba falso)
        es_real = (
            ram_total_gb >= 1 and 
            disco_total_gb >= 10 and 
            cpu_nucleos >= 1 and
            python_version >= "3.8"
        )
        estado = "✅ DISPOSITIVO REAL Y VÁLIDO" if es_real else "⚠️  EQUIPO CON POCOS RECURSOS"
        
        # Imprimir resumen claro
        print("="*60)
        print(f"🔍 VERIFICACIÓN DE TU DISPOSITIVO (ejecutándose AHORA):")
        print("="*60)
        print(f"   Equipo: {nombre_equipo}")
        print(f"   Sistema: {so} | {arquitectura}")
        print(f"   CPU: {cpu_nombre} ({cpu_nucleos} núcleos) | Uso ahora: {cpu_uso_actual}%")
        print(f"   RAM: {ram_libre_gb} GB libres de {ram_total_gb} GB total")
        print(f"   Disco: {disco_libre_gb} GB libres de {disco_total_gb} GB total")
        print(f"   Python: v{python_version}")
        print(f"   Estado: {estado}")
        print("   ℹ️  Sin ubicación | Sin datos personales | Todo local\n")
        
        return {
            "so": so, "cpu": cpu_nombre, "ram_gb": ram_total_gb,
            "disco_gb": disco_total_gb, "python": python_version,
            "es_valido": es_real, "estado": estado
        }
    except Exception as e:
        print(f"\n⚠️  No se pudo verificar el dispositivo: {str(e)[:60]}")
        return {"es_valido": True, "estado": "Verificación omitida"}

# ==================================================
# 1. DEMANDA REAL EN EE.UU. (Google Trends)
# ==================================================
def verificar_demanda_usa(palabra_clave: str) -> dict:
    try:
        pytrends = TrendReq(hl='en-US', tz=360)
        pytrends.build_payload([palabra_clave], cat=0, timeframe='today 12-m', geo='US', gprop='')
        datos = pytrends.interest_over_time()
        if datos.empty:
            return {"promedio":0,"actual":0,"tendencia":"Sin datos","ok":False}
        prom = round(datos[palabra_clave].mean(),1)
        act = round(datos[palabra_clave].iloc[-1],1)
        tend = "CRECIENTE" if act>prom else "ESTABLE" if act==prom else "BAJANDO"
        print(f"📊 DEMANDA EE.UU. (Google Trends):\n   Prom 12m: {prom}/100 | Último mes: {act}/100 | Tendencia: {tend}\n")
        return {"promedio":prom,"actual":act,"tendencia":tend,"ok":True}
    except Exception as e:
        print(f"⚠️  Google Trends no disponible: {str(e)[:50]}\n")
        return {"promedio":0,"actual":0,"tendencia":"Error","ok":False}

# ==================================================
# 2. PRECIOS COMPETENCIA REALES (eBay API oficial)
# ==================================================
def precios_competencia_ebay(producto: str, client_id: str) -> dict:
    if not client_id or client_id == "TU_CLIENT_ID_AQUI":
        ref = round(PRECIO_VENTA_OBJETIVO_USD*0.95,2)
        print(f"🏷️  COMPETENCIA (sin eBay ID): precios referencia ${ref} USD promedio\n")
        return {"prom":ref,"min":round(ref*0.7,2),"max":round(ref*1.3,2),"n":0,"ok":False}
    try:
        r = requests.get(
            "https://api.ebay.com/buy/browse/v1/item_summary/search",
            headers={"Authorization":f"Bearer {client_id}","X-EBAY-C-MARKETPLACE-ID":"EBAY_US"},
            params={"q":producto,"limit":50,"filter":"conditions:{NEW}"},
            timeout=10
        )
        r.raise_for_status()
        precios = [float(i["price"]["value"]) for i in r.json().get("itemSummaries",[]) if 5<float(i["price"]["value"])<500]
        if not precios:
            return {"prom":0,"min":0,"max":0,"n":0,"ok":False}
        prom,mn,mx = round(sum(precios)/len(precios),2),round(min(precios),2),round(max(precios),2)
        print(f"🏷️  COMPETENCIA eBay EE.UU. ({len(precios)} productos nuevos):\n   Prom: ${prom} | Mín: ${mn} | Máx: ${mx}\n")
        return {"prom":prom,"min":mn,"max":mx,"n":len(precios),"ok":True}
    except Exception as e:
        print(f"⚠️  eBay API error: {str(e)[:50]}\n")
        return {"prom":PRECIO_VENTA_OBJETIVO_USD*0.95,"min":0,"max":0,"n":0,"ok":False}

# ==================================================
# 3. ENVÍOS REALES XALAPA → EE.UU. (SEPOMEX/DHL 2026)
# ==================================================
def calcular_envio_mxn(peso_g: float) -> dict:
    kg = peso_g/1000
    # SEPOMEX Paquete Internacional Aéreo (7-15 días)
    sepomex = 235 if kg<=0.5 else 389 if kg<=1 else 612 if kg<=2 else 612+(kg-2)*220
    # DHL Express Worldwide (2-3 días)
    dhl = 890 if kg<=0.5 else 1120 if kg<=1 else 1450 if kg<=2 else 1450+(kg-2)*310
    print(f"📦 ENVÍO XALAPA → EE.UU. ({peso_g}g):\n   SEPOMEX: ${round(sepomex,2)} MXN (${round(sepomex/TIPO_CAMBIO_USD_MXN,2)} USD) | 7-15d\n   DHL: ${round(dhl,2)} MXN (${round(dhl/TIPO_CAMBIO_USD_MXN,2)} USD) | 2-3d\n")
    return {"sepomex":round(sepomex,2),"dhl":round(dhl,2)}

# ==================================================
# 4. RENTABILIDAD FINAL (con TODOS los costos reales)
# ==================================================
def calcular_rentabilidad(costo_mxn: float, precio_usd: float, envios: dict, comp: dict) -> dict:
    p_mxn = precio_usd * TIPO_CAMBIO_USD_MXN
    comision = p_mxn*0.13   # eBay/Amazon promedio
    arancel = p_mxn*0.04    # Aduana EE.UU. promedio
    iva_usa = p_mxn*0.07    # Impuesto ventas promedio
    pago = p_mxn*0.03 + 5   # PayPal/Stripe (~3% + $5 MXN fijos)
    
    res = {}
    for nombre, env_mxn in [("SEPOMEX",envios["sepomex"]),("DHL",envios["dhl"])]:
        ct = costo_mxn + env_mxn + comision + arancel + iva_usa + pago
        gan = p_mxn - ct
        marg = round((gan/p_mxn)*100,1)
        rec = "✅ Precio competitivo" if precio_usd<=comp["prom"] else "⚠️  Más caro que la competencia"
        rec += " | ❌ NO RENTABLE" if marg<10 else " | ✅ RENTABLE" if marg>20 else " | ⚠️  Margen bajo"
        res[nombre] = {
            "ingreso":round(p_mxn,2),"costo_total":round(ct,2),
            "ganancia_mxn":round(gan,2),"ganancia_usd":round(gan/TIPO_CAMBIO_USD_MXN,2),
            "margen":marg,"recomendacion":rec
        }
        print(f"💰 {nombre} (${precio_usd} USD):\n   Ingreso: ${res[nombre]['ingreso']} MXN | Costo total: ${res[nombre]['costo_total']} MXN\n   GANANCIA NETA: ${res[nombre]['ganancia_mxn']} MXN (${res[nombre]['ganancia_usd']} USD) | Margen: {marg}%\n   {rec}\n")
    return res

# ==================================================
# EJECUTAR TODO EN ORDEN
# ==================================================
if __name__ == "__main__":
    # PASO 0: Verificar TU dispositivo primero (100% local)
    disp = verificar_dispositivo_local()
    time.sleep(1)
    
    # Si el equipo no es válido, avisa pero sigue (por si acaso)
    if not disp["es_valido"]:
        print("⚠️  Tu equipo tiene pocos recursos — el proceso puede ir lento, pero seguirá.\n")
    
    # PASO 1-4: Validación del producto en USA (datos reales de APIs)
    print("="*60)
    print(f"VALIDACIÓN DE PRODUCTO PARA VENDER EN EE.UU.: {NOMBRE_PRODUCTO.upper()}")
    print("="*60)
    
    demanda = verificar_demanda_usa(PALABRA_CLAVE_BUSQUEDA)
    time.sleep(2)
    comp = precios_competencia_ebay(NOMBRE_PRODUCTO, EBAY_CLIENT_ID)
    time.sleep(1)
    envios = calcular_envio_mxn(PESO_PRODUCTO_GRAMOS)
    rent = calcular_rentabilidad(COSTO_TU_PRODUCTO_MXN, PRECIO_VENTA_OBJETIVO_USD, envios, comp)
    
    # CONCLUSIÓN FINAL
    print("="*60)
    print("🎯 CONCLUSIÓN FINAL PARA VENDER:")
    print("="*60)
    vende = disp["es_valido"] and demanda["actual"]>=30 and rent["SEPOMEX"]["margen"]>=15
    if vende:
        print("🎉 SÍ VALE LA PENA: Tu equipo es válido + hay demanda + margen aceptable")
        print(f"   Acción: Empieza con SEPOMEX para probar, escala a DHL cuando vendas mucho.")
    else:
        print("❌ NO LO VENDAS ASÍ — ajusta algo:")
        if not disp["es_valido"]: print("   → Actualiza Python a ≥3.8 o libera RAM/disco")
        if demanda["actual"]<30: print("   → Cambia producto/palabra clave (poca demanda en EE.UU.)")
        if rent["SEPOMEX"]["margen"]<15: print("   → Baja tu costo, sube el precio o reduce peso de envío")