── The Boomer Dev Docs ← Volver a la app

MEMORIA FUNCIONAL — ShopifySync

Documento generado a partir del código real del proyecto (code/frontend/ React SPA + code/backend/ FastAPI). Fecha: 2026-08-05 · Live: https://shopify-sync.theboomer.dev


1. Introducción

ShopifySync es un SaaS que sincroniza productos entre tiendas Shopify y Google Sheets en ambas direcciones. El usuario conecta sus tiendas Shopify (dominio + access token) y sus hojas de cálculo de Google (spreadsheet ID + tokens), configura el mapeo de columnas (qué columna de la hoja corresponde a qué campo de Shopify) y ejecuta sincronizaciones manuales, con planes de pago vía Stripe (Free / Pro / Pro API).

Arquitectura real

Capa Tecnología Ruta
Frontend React + Vite + React Router + TanStack Query + Zustand (persist) + Tailwind + sonner (toasts) code/frontend/src/
Backend FastAPI (Python) — routers: auth, billing, sync, sync_history, webhooks, sync_config code/backend/app/
Servicios Shopify API (paginación por cursor, inventory levels), Google Sheets API, motor de sync, Stripe code/backend/app/services/
Persistencia Repositorios de usuario/tienda/hoja/config (Motor/MongoDB async) code/backend/app/models/

Stack frontend real: App.tsx monta QueryClientProvider (react-query) + BrowserRouter + Toaster (sonner). La autenticación se guarda en Zustand con persist bajo la clave shopify-sync-auth. El API client (lib/api.ts) apunta a VITE_API_URL (default http://localhost:9100) y añade Authorization: Bearer <token>.

Nota: el backend eliminó los endpoints OAuth (# OAuth endpoints removed - using direct token input instead): el usuario pega los tokens de Google/Shopify directamente en los formularios.


2. Tipos de usuario

Tipo Descripción Alcance real en el código
Visitante Sin sesión Redirigido a /login (guard del layout).
Usuario autenticado Login con email (o registro con email + nombre) Accede al dashboard completo: Stores, Sheets, Mapping, Settings. Plan por defecto free.
Plan Free $0 1 tienda, 1 hoja, sync manual (según tarjetas de planes en Settings).
Plan Pro $7/mes 5 tiendas, 5 hojas, auto sync, soporte prioritario (precios/features de UI).
Plan Pro API $12/mes Tiendas y hojas ilimitadas, acceso API, soporte prioritario.

3. Funcionalidades

F3.1 — Autenticación (Login / Registro) — pages/Login.tsx

F3.2 — Layout de dashboard con guard de auth — components/DashboardLayout.tsx

F3.3 — Dashboard / Home — pages/Home.tsx

F3.4 — Stores (tiendas Shopify) — pages/Stores.tsx

F3.5 — Sheets (hojas de Google) — pages/Sheets.tsx

F3.6 — Mapping de columnas — pages/Mapping.tsx

F3.7 — Settings (cuenta y billing) — pages/Settings.tsx

F3.8 — Sincronización (motor backend) — app/services/sync_engine.py + app/api/sync.py

F3.9 — API de configuración de sync — app/api/sync_config.py

F3.10 — Billing Stripe — app/api/billing.py + app/services/stripe.py

F3.11 — Webhooks y rate limiting (backend)


4. Pantallas (wireframes textuales)

P1 — Login (/login)

┌────────────────────────────────────────────────────┐
│          (centrado vertical/horizontal, bg-slate-50)│
│  ┌──────────────────────────────────────────────┐  │
│  │  [🛍 icono]  ShopifySync                     │  │
│  │                                              │  │
│  │  [banner rojo si error]                      │  │
│  │                                              │  │
│  │  Email                                      │  │
│  │  [________________________]                 │  │
│  │  Name  (solo en modo registro)              │  │
│  │  [________________________]                 │  │
│  │                                              │  │
│  │  [     Sign In / Create Account     ] (negro)│  │
│  │                                              │  │
│  │  Need an account? Sign up  (toggle azul)    │  │
│  └──────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────┘

P2 — Dashboard (/)

┌──────────────┬───────────────────────────────────────────┐
│ SIDEBAR      │  Dashboard                                │
│ (slate-900)  │  Manage your Shopify and Google Sheets sync│
│              │                                           │
│ ShopifySync  │  ┌──────────┐ ┌──────────┐ ┌──────────┐   │
│              │  │ [🛍] 2   │ │ [📋] 1   │ │ [📦] 0   │   │
│ ● Dashboard  │  │ Stores   │ │ Sheets   │ │ Synced   │   │
│   Stores     │  └──────────┘ └──────────┘ └──────────┘   │
│   Sheets     │                                           │
│   Mapping    │  Quick Actions                            │
│   Settings   │  [↻ Sync Now]  mistore.myshopify.com → Inv│
│              │  (o: Connect at least one store and one   │
│ ─────────────│     sheet… [Add Store →] [Add Sheet →])   │
│ 👤 Nombre    │  [banner verde: Synced N products ...]    │
│    email     │                                           │
│ [⏻ Logout]  │  Connected Services                       │
│              │  [🛍] mistore.myshopify.com                │
│              │  [📋] My Inventory                        │
└──────────────┴───────────────────────────────────────────┘

P3 — Stores (/stores)

┌──────────────┬───────────────────────────────────────────┐
│ SIDEBAR      │  Stores                                   │
│ (activa:     │  Connect your Shopify stores              │
│  Stores)     │                                           │
│              │  Add New Store                            │
│              │  Shopify Domain  [mystore.myshopify.com]  │
│              │  Access Token   [•••••••• (shpat_...)]    │
│              │  [+ Add Store]                           │
│              │                                           │
│              │  Connected Stores (2)                     │
│              │  [🛍] mystore.myshopify.com       [🗑]     │
│              │      <location_id> / No location set      │
│              │  (vacío → "No stores connected")          │
└──────────────┴───────────────────────────────────────────┘

P4 — Sheets (/sheets)

┌──────────────┬───────────────────────────────────────────┐
│ SIDEBAR      │  Sheets                                   │
│ (activa:     │  Connect your Google Sheets               │
│  Sheets)     │                                           │
│              │  Add New Sheet                            │
│              │  Spreadsheet ID [1abc...]  Name [My Inv.] │
│              │  Sheet Name    [Sheet1]                   │
│              │  Google Access Token  [•••• (ya29...)]    │
│              │  Google Refresh Token [•••• (1//...)]     │
│              │  [+ Add Sheet]                           │
│              │                                           │
│              │  Connected Sheets (1)                     │
│              │  [📋] My Inventory                [🗑]     │
│              │      Sheet1 • 1abc12345678901...          │
└──────────────┴───────────────────────────────────────────┘

P5 — Mapping (/mapping)

┌──────────────┬───────────────────────────────────────────┐
│ SIDEBAR      │  Column Mapping                           │
│ (activa:     │  Configure which columns in your Google   │
│  Mapping)    │  Sheet map to Shopify fields              │
│              │                                           │
│              │  Sync Configurations       [+ Add Config] │
│              │  [⇄] <store_id>            [Edit] [🗑]    │
│              │      <sheet_id> → Shopify                 │
│              │  (vacío → "No sync configurations yet.")  │
│              │                                           │
│              │  ┌ MODAL (overlay) ────────────────────┐  │
│              │  │ Create/Edit Sync Configuration      │  │
│              │  │ Shopify Store [________]  Sheet [__]│  │
│              │  │ Sync Direction [Sheet → Shopify ▾]  │  │
│              │  │ Column Mapping        [+ Add Mapping]│  │
│              │  │ [SKU ▾] → [SKU ▾]              [🗑] │  │
│              │  │ [Stock ▾] → [Inventory Qty ▾] [🗑] │  │
│              │  │                      [Cancel][Save] │  │
│              │  └────────────────────────────────────┘  │
└──────────────┴───────────────────────────────────────────┘

P6 — Settings (/settings)

┌──────────────┬───────────────────────────────────────────┐
│ SIDEBAR      │  Settings                                 │
│ (activa:     │  Manage your account and billing          │
│  Settings)   │                                           │
│              │  Current Plan                             │
│              │  ┌─────────────────────────────────────┐  │
│              │  │ Pro            Billing active       │  │
│              │  │                   [Manage Billing →]│  │
│              │  └─────────────────────────────────────┘  │
│              │                                           │
│              │  Available Plans                          │
│              │  ┌ Free ──────┐ ┌ Pro ───────┐ ┌ Pro API ┐│
│              │  │ $0         │ │ $7/mo      │ │ $12/mo  ││
│              │  │ ✓1 store   │ │ ✓5 stores  │ │ ✓Unlim. ││
│              │  │ ✓1 sheet   │ │ ✓5 sheets  │ │ ✓API    ││
│              │  │ ✓Manual    │ │ ✓Auto sync │ │ ✓Priori ││
│              │  │ [Current]  │ │ [Current]  │ │[Upgrade]││
│              │  └────────────┘ └────────────┘ └─────────┘│
│              │                                           │
│              │  Account Information                      │
│              │  Name   Juan                             │
│              │  Email  juan@example.com                 │
└──────────────┴───────────────────────────────────────────┘

5. Flujos de trabajo

Flujo A — Primer uso (registro → conexión → sync)

  1. El visitante accede a / → redirigido a /login (guard del layout).
  2. Hace Sign up (email + nombre) o Sign In (email) → token guardado en Zustand persist → vuelve a /.
  3. En /stores añade su tienda Shopify (dominio + shpat_...) → POST /sync/store.
  4. En /sheets añade su hoja (spreadsheet ID/nombre, sheet name, tokens Google) → POST /sync/sheet.
  5. En /mapping crea una configuración (store, sheet, dirección, mapeo de columnas) → POST /sync/config.
  6. En el dashboard pulsa Sync NowPOST /sync/run (usa la 1ª tienda y 1ª hoja, shopify_to_sheet) → banner verde con nº de productos sincronizados.
  7. Si el plan lo permite (Pro+), puede gestionar billing desde Settings.

Flujo B — Conexión de una tienda

  1. Abrir /stores → rellenar Shopify Domain + Access Token (campos required).
  2. Pulsar Add Store → POST; en error solo se loguea en consola (sin mensaje UI).
  3. La tienda aparece en Connected Stores (N) con su location (o No location set).
  4. Eliminación: papelera → confirm("Delete this store?") → DELETE → recarga.

Flujo C — Configurar un mapeo de columnas

  1. Abrir /mapping+ Add Configuration.
  2. En el modal: escribir store y sheet, elegir dirección (Sheet → Shopify o Shopify → Sheet).
  3. Añadir filas de mapeo: columna de la hoja (con sugerencias SKU/Product/Stock/…) → campo Shopify (select SKU/Title/Price/Inventory…).
  4. Save → POST (nuevo) o PATCH (existente) → la config aparece en la lista con su dirección.
  5. Editar reabre el modal con los datos; borrar pide confirmación.

Flujo D — Sincronización Shopify → Sheet

  1. Backend pagina los productos de Shopify (50/cursor) hasta agotar.
  2. Recoge todos los inventory_item_id y consulta inventory levels.
  3. Construye filas {SKU, Stock} y las escribe en la hoja desde fila 2, columna A.
  4. Responde products_synced y errors (si hubo). El dashboard muestra el resultado.

Flujo E — Sincronización Sheet → Shopify

  1. Backend lee los productos de la hoja.
  2. Obtiene productos actuales de Shopify (250) y construye mapa por SKU.
  3. Actualiza stock en Shopify según los valores de la hoja.
  4. Devuelve products_synced/errors.

Flujo F — Upgrade de plan

  1. /settings → ver plan actual + tarjetas de planes.
  2. Upgrade en Pro o Pro API → POST /billing/checkout → redirección a Stripe Checkout.
  3. Tras pagar, stripe_customer_id queda en el usuario → Settings muestra Billing active y Manage Billing → (portal).

Flujo G — Cierre de sesión

  1. Botón Logout en la sidebar → clearAuth() (borra token/usuario del store persistido) → /login.

6. Reglas de negocio

  1. Acceso restringido: toda ruta del dashboard requiere isAuthenticated; si no, redirección a /login.
  2. Auth por email (magic/simple): login solo con email; registro con email + nombre; token Bearer almacenado en localStorage (Zustand persist).
  3. Límites por plan (según UI de Settings): Free = 1 tienda, 1 hoja, sync manual; Pro = 5 tiendas, 5 hojas, auto sync, soporte prioritario; Pro API = ilimitado, acceso API. (Los límites se muestran en la UI; el enforcement efectivo depende del backend/Stripe.)
  4. Conexiones por token directo: no hay OAuth en UI; el usuario pega shopify_access_token y los tokens de Google (access + refresh) en los formularios (los campos se muestran como password).
  5. Sync rápido del dashboard: usa stores[0] y sheets[0] con dirección fija shopify_to_sheet; el mapeo avanzado se gestiona en /mapping.
  6. Direcciones válidas de sync: sheet_to_shopify (Sheet → Shopify) y shopify_to_sheet (Shopify → Sheet).
  7. Formato de la hoja: para sync se espera hoja llamada Sheet1 con columnas SKU y Stock (SKU/Stock a partir de fila 2 en shopify_to_sheet; en sheet_to_shopify se leen los productos de la hoja).
  8. Campos mapeables de Shopify: sku, title, price, inventory_quantity, barcode, weight, grams, requires_shipping, taxable.
  9. Eliminaciones con confirmación: tiendas, hojas y configuraciones piden confirm() antes de borrar.
  10. Billing mensual: checkout y portal usan intervalo monthly; plan por defecto free; stripe_customer_id indica billing activo.
  11. Tolerancia a errores de sync: los errores de Shopify/Sheets se capturan y se devuelven en errors (el sync no aborta con excepción).
  12. Errores de API: el cliente lanza ApiError(status, detail) con el detail del backend (o "Request failed"); las páginas loguean en consola — solo Login muestra el error en pantalla.
  13. Rate limiting y webhooks: la API incluye core/rate_limit.py y un router de webhooks (app/api/webhooks.py).