# 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**: ``, `` — usar el namespace `eanucc:` para las consultas XPath - **Sin prefijo**: ``, `` — 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.