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>
This commit is contained in:
commit
901dd8763d
47 files changed
+4709
No files matched your search
@@ -0,0 +1,61 @@
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
|
||||
def resolver_location(store_config: Dict[str, Any], location_id: Any) -> Optional[Dict[str, Any]]:
|
||||
"""Config (is_store/warehouse_code) para un location_id de Shopify, o None si no está mapeado."""
|
||||
return store_config["sap"]["locations"].get(str(location_id))
|
||||
|
||||
|
||||
def es_tienda(store_config: Dict[str, Any], location_id: Any) -> bool:
|
||||
"""
|
||||
True si este location_id es una tienda física (genera StockTransfer +
|
||||
Delivery además de la ITR); False si es un CD (solo ITR).
|
||||
"""
|
||||
location = resolver_location(store_config, location_id)
|
||||
return bool(location and location.get("is_store"))
|
||||
|
||||
|
||||
def construir_inventory_transfer_request(
|
||||
order: Dict[str, Any],
|
||||
fulfillment: Dict[str, Any],
|
||||
store_config: Dict[str, Any],
|
||||
warehouse_code: str,
|
||||
invoice: Dict[str, Any],
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Arma el JSON para POST InventoryTransferRequests: una solicitud por cada
|
||||
fulfillment, moviendo stock desde la bodega real del location_id hacia
|
||||
la bodega virtual usada en el Invoice (default_warehouse_invoice). Usa
|
||||
los line_items propios del fulfillment (no los de toda la orden), ya
|
||||
que una orden puede tener varios fulfillments con distintos
|
||||
ítems/cantidades. CardCode/CardName se toman del Invoice; Comments lleva
|
||||
el "name" de Shopify para poder ubicarla fácil.
|
||||
"""
|
||||
to_warehouse = store_config["sap"]["default_warehouse_invoice"]
|
||||
series = store_config["sap"]["numbering_series"]["INVENTORY_TRANSFER_REQUEST"]
|
||||
doc_date = order["created_at"][:10]
|
||||
|
||||
document_lines = [
|
||||
{
|
||||
"ItemCode": item["sku"],
|
||||
"Quantity": item["quantity"],
|
||||
"FromWarehouseCode": warehouse_code,
|
||||
"WarehouseCode": to_warehouse,
|
||||
}
|
||||
for item in fulfillment.get("line_items", [])
|
||||
if item.get("sku")
|
||||
]
|
||||
|
||||
return {
|
||||
"CardCode": invoice["CardCode"],
|
||||
"CardName": invoice["CardName"],
|
||||
"Comments": order.get("name"),
|
||||
"DocDate": doc_date,
|
||||
"DueDate": doc_date,
|
||||
"Series": series,
|
||||
"FromWarehouse": warehouse_code,
|
||||
"ToWarehouse": to_warehouse,
|
||||
"U_ShopifyOrderId": order["id"],
|
||||
"U_ShopifyStore": store_config["store_code"],
|
||||
"StockTransferLines": document_lines,
|
||||
}
|
||||
Reference in new issue
Block a user