Files
shopify_run_run/docs/esquema_base_datos.md
T
georgeandClaude Sonnet 5.5 901dd8763d Integración Shopify → SAP Business One (snobbycl y on-chile)
Pipeline de integración de órdenes de Shopify a SAP Service Layer:
Invoice de reserva, pago con tarjeta o transferencia por transacción,
solicitud de traslado, traslado de stock y entrega.

- Invoice igual a lo cobrado; fulfillments limitados a lo facturado
- Estados terminales integrated, timeout, ignored y cancelled
- Idempotencia contra SAP: adopta documentos existentes en vez de duplicar
- Reintentos de red en el cliente de Shopify
- Secretos fuera de los JSON de tienda (${VARIABLE} resuelta desde .env)
- Herramientas de consulta, integración puntual y carga de pruebas
- Documentación en docs/ (flujo, casos especiales, mapeo, configuración)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 19:22:40 -05:00

7.1 KiB

Esquema de base de datos (SQLite)

Archivo: data/shopify_sap.db. Definido y accedido desde core/db.py. Tres tablas: orders (cabecera), order_fulfillments (un fulfillment de Shopify) y order_documents (un documento SAP requerido/creado).

erDiagram
    orders ||--o{ order_fulfillments : "tiene"
    orders ||--o{ order_documents : "tiene"
    order_fulfillments ||--o{ order_documents : "tiene (si aplica)"

    orders {
        int sys_id PK
        string store_code
        int shopify_order_id
        string order_number
        string tags
        string payment_gateway_names
        string shopify_created_at
        string time_insert
        string time_update
        string financial_status
        string fulfillment_status
        string card_code
        string status
        string last_error
    }
    order_fulfillments {
        int sys_id PK
        int order_sys_id FK
        int shopify_fulfillment_id
        string location_id
        bool is_store
        string warehouse_code
        string time_insert
    }
    order_documents {
        int sys_id PK
        int order_sys_id FK
        int fulfillment_sys_id FK
        string doc_type
        int sequence
        bool required
        string status
        int sap_doc_entry
        int sap_doc_num
        int base_doc_entry
        string error_message
        int attempts
        string time_update
    }

orders

Una fila por orden de Shopify (UNIQUE(store_code, shopify_order_id), así el mismo id de Shopify puede repetirse entre tiendas distintas).

Columna Tipo Descripción
sys_id INTEGER PK id interno, autoincremental
store_code TEXT qué tienda (config/stores/<store_code>.json)
shopify_order_id INTEGER id de Shopify
order_number TEXT campo name de Shopify (ej. "#7863")
tags TEXT tal cual viene de Shopify, separado por coma
payment_gateway_names TEXT medio(s) de pago, unidos con " + " si hay más de uno
shopify_created_at TEXT fecha de creación real en Shopify — dispara el timeout
time_insert TEXT cuándo se descargó/insertó por primera vez (auditoría)
time_update TEXT última vez que se tocó esta orden — define el orden de la cola (ver status)
financial_status TEXT último valor conocido de Shopify (puede cambiar entre corridas)
fulfillment_status TEXT ídem — null/partial/fulfilled
card_code TEXT CardCode de SAP ya resuelto (se cachea, no se vuelve a resolver)
status TEXT ver tabla de estados abajo
last_error TEXT último mensaje de error (ya diagnosticado, no el crudo de SAP si se reconoció)

Valores de status

Valor Terminal Significado
pending No Cabecera descargada, aún no analizada
not_eligible No No está paid, o no tiene fulfillments todavía
in_progress No Tiene al menos un fulfillment procesado, pero fulfillment_status != "fulfilled" (pueden llegar más)
error No El último intento falló en algún documento; se reintenta en la próxima rotación
integrated Sí Todos los documentos requeridos están created y fulfillment_status == "fulfilled"
timeout Sí Pasaron más de timeout_days desde shopify_created_at sin llegar a integrated
cancelled Sí La orden tiene cancelled_at en Shopify (anulada). El pipeline la marca solo, con la fecha y el cancel_reason en last_error; nunca crea documentos en SAP
ignored Sí Marcada a mano para que el pipeline no la procese nunca (ej. pedidos de prueba). No se asigna automáticamente

Solo integrated, timeout, ignored y cancelled son terminales — get_pending_orders y mark_orders_timeout excluyen esos cuatro, todo lo demás se sigue reintentando.


order_fulfillments

Una fila por fulfillment de Shopify (UNIQUE(order_sys_id, shopify_fulfillment_id)). Una orden puede tener varios (envío parcial).

Columna Tipo Descripción
sys_id INTEGER PK
order_sys_id FK → orders.sys_id
shopify_fulfillment_id INTEGER id del fulfillment en Shopify
location_id TEXT location_id de Shopify de ese fulfillment
is_store INTEGER (bool) snapshot de config.sap.locations[location_id].is_store al momento de procesarlo
warehouse_code TEXT bodega SAP resuelta para ese location_id
time_insert TEXT cuándo se detectó este fulfillment

order_documents

Una fila por documento SAP requerido (exista o no todavía). Documentos a nivel orden (INVOICE, INCOMING_PAYMENT) tienen fulfillment_sys_id = NULL; los de nivel fulfillment (INVENTORY_TRANSFER_REQUEST, STOCK_TRANSFER, DELIVERY) lo tienen seteado.

Columna Tipo Descripción
sys_id INTEGER PK
order_sys_id FK → orders.sys_id
fulfillment_sys_id FK → order_fulfillments.sys_id, nullable NULL para documentos de orden
doc_type TEXT INVOICE, INCOMING_PAYMENT, INVENTORY_TRANSFER_REQUEST, STOCK_TRANSFER, DELIVERY
sequence INTEGER orden de creación (10/20/30/40/50 — incrementos de 10 para insertar tipos nuevos sin reordenar)
required INTEGER (bool) si este documento aplica para esta orden/fulfillment
status TEXT pending / created / error
sap_doc_entry / sap_doc_num INTEGER identificadores reales en SAP, una vez creado
base_doc_entry INTEGER (reservado, no usado todavía — el BaseEntry real se arma al vuelo en domain/* a partir del documento base)
error_message TEXT mensaje ya diagnosticado (ver domain/documents.py::diagnosticar_error)
attempts INTEGER cuántas veces falló
time_update TEXT última vez que se tocó esta fila

Valores de status

Valor Significado
pending Fila creada (el documento es requerido), todavía no se intentó
created Ya existe en SAP (sap_doc_entry/sap_doc_num poblados) — en un reintento, se relee con GET en vez de volver a crear
error Falló el último intento — se reintenta en la próxima corrida

Funciones de core/db.py por tabla

orders: insert_order_header, get_last_shopify_order_id, get_order_sys_id, mark_orders_timeout, get_pending_orders, set_order_status, set_order_card_code, update_order_snapshot.

order_fulfillments: ensure_order_fulfillment (insert-si-no-existe, por shopify_fulfillment_id).

order_documents: ensure_order_document (insert-si-no-existe, por doc_type + fulfillment_sys_id), get_order_document, mark_document_created, mark_document_error.


Nota: precisión de time_update

Todos los UPDATE/DEFAULT de timestamp usan strftime('%Y-%m-%d %H:%M:%f','now') (milisegundos), no datetime('now') (que solo tiene precisión de segundo). Esto es necesario para que la rotación justa de get_pending_orders (ORDER BY time_update ASC) funcione bien cuando el pipeline toca varias órdenes rápido dentro del mismo segundo.