Files
comercio-net/docs/parser_spec.md
T

9.2 KiB
Raw Blame History

Especificación de Parseo — Órdenes de Compra CommerceNet Chile

Formato del archivo

  • XML con esquema EAN.UCC (GS1) basado en As2Envelope.xsd
  • Codificación: ISO-8859-1
  • Namespace: http://www.uc-council.org/smp/schemas/eanucc

Estructura del XML

envelope
├── messageHeader
│   ├── creationDate
│   ├── userId
│   ├── messageIdentifier
│   ├── to/gln
│   ├── from/gln
│   └── representingParty/gln
└── body
    └── transaction
        └── command
            └── documentCommand
                ├── documentCommandHeader (@type="ADD")
                └── documentCommandOperand
                    └── order
                        ├── @creationDate
                        ├── @documentStatus
                        ├── paymentTerms
                        │   ├── @type
                        │   ├── @eventType
                        │   └── netPayment/timePeriodDue (@type, value)
                        ├── movementDate
                        ├── movementDateType
                        ├── typedEntityIdentification (@entityType="ORDER")
                        │   └── entityIdentification
                        │       ├── uniqueCreatorIdentification  ← N° OC
                        │       └── contentOwner/gln
                        ├── specialHandling
                        ├── salesDepartamentNumber
                        ├── orderType
                        ├── promotionDealNumber
                        ├── internalVendorNumber
                        ├── buyer/gln
                        ├── seller/gln
                        ├── shipParty (@identificationType="SHIP_TO")/gln
                        ├── shipFrom/name
                        ├── currency
                        ├── mainCarrierTransport
                        │   ├── mode
                        │   ├── means
                        │   └── carrierName
                        └── lineItem (@number)
                            ├── netPrice/amount (@currencyISOcode)
                            ├── PriceType
                            ├── requestedQuantity (@UnitType)
                            ├── containedUnits (@UnitType)
                            ├── allowanceCharge (0..N)
                            │   ├── @allowanceOrChargeType ("ALLOWANCE" | "CHARGE")
                            │   └── monetaryAmountOrPercentage
                            │       ├── percentage
                            │       └── amount (@currencyISOcode)
                            ├── itemIdentification
                            │   ├── gtin
                            │   ├── buyerItemNumber (opcional)
                            │   └── vendorItemNumber (opcional)
                            ├── itemColor (opcional)
                            ├── itemSize (opcional)
                            ├── itemDescription (@language)/text
                            └── totalAmount/amount (@currencyISOcode)

Reglas generales

  • Todos los valores provienen exclusivamente del contenido XML
  • El nombre del archivo es solo referencial
  • No inventar campos que no existan en el XML
  • No recortar ni modificar valores

Mapeo Cabecera

Columna Ruta XPath / Campo Notas
Emisor envelope/messageHeader/from/gln
Receptor envelope/messageHeader/to/gln
N° Orden de Compra envelope/body/transaction/command/documentCommand/documentCommandOperand/order/typedEntityIdentification[@entityType='ORDER']/entityIdentification/uniqueCreatorIdentification Valor completo, sin recortes
Fecha generación mensaje envelope/body/transaction/command/documentCommand/documentCommandOperand/order/@creationDate Atributo creationDate del elemento order
Fecha de embarque envelope/body/transaction/command/documentCommand/documentCommandOperand/order/movementDate movementDate con movementDateType REQUESTED_DELIVERY
Fecha de cancelación — No existe en el XML, se deja vacío
Condiciones de pago paymentTerms/netPayment/timePeriodDue Formato: "NET {días} días desde fecha de factura"
Lugar de entrega shipParty[@identificationType='SHIP_TO']/gln
Dpto. ventas salesDepartamentNumber
Tipo OC orderType
Promoción promotionDealNumber
N° Proveedor internalVendorNumber
Observaciones specialHandling

Mapeo Detalle (por línea)

Orden de columnas:

# Columna Ruta XPath Notas
1 Línea lineItem/@number
2 Cód. UPC (GTIN) lineItem/itemIdentification/gtin
3 Item (buyer) lineItem/itemIdentification/buyerItemNumber
4 Cód. Prov. lineItem/itemIdentification/vendorItemNumber
5 Color/Talla/UM itemColor + itemSize Concatenar como "Color / Talla" según lo que traiga cada producto
6 Descripción itemDescription[@language='SP']/text Primer elemento
7 Precio Unit. netPrice/amount Moneda del atributo @currencyISOcode
8 Empaques requestedQuantity Cantidad solicitada en unidades de empaque (CSC = cajas)
9 Unid/Empaque containedUnits Unidades contenidas por empaque (SIN)
10 Cantidad (unid) — Derivado: Empaques × Unid/Empaque
11 Importe totalAmount/amount Moneda del atributo @currencyISOcode

Notas sobre UM

  • requestedQuantity/@UnitType = CSC o CS (Case) → Empaques
  • containedUnits/@UnitType = SIN (Unit) → Unid/Empaque
  • Los campos itemColor e itemSize son opcionales según el emisor. Si no existen, la columna "Color/Talla/UM" se deja vacía.

Algoritmo de Descuentos (allowanceCharge)

Cada línea puede tener 0 o más bloques allowanceCharge. Solo se procesan los de tipo ALLOWANCE con percentage > 0.

base_total = netPrice × requestedQuantity

para cada allowanceCharge con allowanceOrChargeType="ALLOWANCE" y percentage > 0:
    descuento = round(base_total × percentage / 100)    ← round a entero, .5 hacia arriba
    base_total = base_total - descuento

totalAmount (calculado) = base_total

Reglas:

  • Los descuentos se aplican secuencialmente sobre el saldo restante (no todos sobre el original)
  • El percentage y amount en el XML son por unidad, informativos. El cálculo real se hace sobre el total de la línea
  • El resultado final debe coincidir con lineItem/totalAmount/amount
  • Si hay múltiples ALLOWANCE, se encadenan: primero desc % sobre el total original, luego otro % sobre el resultado anterior

Ejemplos validados contra archivos reales:

Lín Precio CS Base Allowances Cálculo totalAmount XML
1 32.230 2 64.460 25% → round(16.115)=16.115; 30% → round(48.345×30%)=14.504 64.460−16.115−14.504 = 33.841 33.841 ✅
2 35.939 38 1.365.682 25% → round(341.420,5)=341.421; 15% → round(1.024.261×15%)=153.639 1.365.682−341.421−153.639 = 870.622 870.622 ✅
9 39.097 1 39.097 25% → round(9.774,25)=9.774 39.097−9.774 = 29.323 29.323 ✅
10 39.097 2 78.194 25% → round(19.548,5)=19.549 78.194−19.549 = 58.645 58.645 ✅
20 170.000 4 680.000 25% → 170.000; 20% → round(510.000×20%)=102.000 680.000−170.000−102.000 = 408.000 408.000 ✅

Mapeo Totales Finales

Columna Ruta XPath / Derivación Notas
Importe total Suma de lineItem/totalAmount/amount O también order/totalAmount si existiera
Etapa de transporte mainCarrierTransport/mode
Quien transporta mainCarrierTransport/carrierName
Divisa de referencia currency
Condiciones de entrega — No existe en el XML

Diferencias entre emisores

Elemento Walmart (925485K200) Otros emisores
Namespace Sin prefijo (xmlns=) Con prefijo eanucc:
requestedQuantity/@UnitType CSC CS
itemColor, itemSize Presente Ausente
buyerItemNumber, vendorItemNumber Presente Ausente
salesDepartamentNumber, orderType Presente Ausente
promotionDealNumber POS REPLEN Ausente
internalVendorNumber Presente Ausente
specialHandling NO PRETICKET Ausente
mainCarrierTransport, currency Presente Ausente
allowanceCharge Ausente Presente (con descuentos reales o en 0)

Diferencia entre tipos de OC

  • orderType=20: Tipo estándar
  • orderType=33: Tipo distinto (ej. reposición directa)
  • Ambos con promotionDealNumber="POS REPLEN"

Manejo de Namespace

Los archivos pueden venir con o sin prefijo:

  • Con prefijo: <eanucc:envelope>, <eanucc:order> — usar el namespace eanucc: para las consultas XPath
  • Sin prefijo: <envelope>, <order> — namespace por default

Solución recomendada: registrar ambos namespaces y usar * o registrar el namespace URI http://www.uc-council.org/smp/schemas/eanucc con un alias en el parser.