Hace poco tuve que modificar unos documentos de márketing (ofertas y pedidos de ventas) vía B1WS/Di Server. Hasta el momento, sólo había creado documentos de SAP y supuse que la edición seguiría el mismo proceso que con los UDO, con los que tengo bastante más manejo. Básicamente, el proceso con un UDO es:
-
Obtengo el objeto sin modificar vía B1WS.
-
Modifico los campos de la cabecera con los datos nuevos.
-
Con el array de líneas, agrego las nuevas, elimino las que hay que borrar y modifico los campos de las que hay que modificar.
-
Le vuelvo a enviar todo a SAP.
Con las líneas, que es lo que me importa aquí, el proceso es como éste, siendo Origen el objeto con los cambios que envía la capa de lógica de negocio y Destino, el objeto sin modificar recuperado de SAP. Como pueden observar, hay una propiedad en las filas origen que me indica qué debo hacer con ellas:
Private Sub RellenarLineas(Origen As IHorasCabecera, Destino As Horas.Horas) Dim oLineas As List(Of Horas.HorasCDA_HOR1) Dim oLinea As Horas.HorasCDA_HOR1 If Destino.CDA_HOR1Collection?.Length > 0Then oLineas = Destino.CDA_HOR1Collection.ToList Else oLineas = New List(Of Horas.HorasCDA_HOR1) End If If Origen.Detalles?.Any Then For Each mLinea In Origen.Detalles Select Case mLinea.OperacionGuardado Case EGuardadoTipoOperacion.Nuevo oLinea = New Horas.HorasCDA_HOR1 RellenarLinea(mLinea, oLinea) oLineas.Add(oLinea) Case EGuardadoTipoOperacion.Modificar oLinea = oLineas.Where(Function(x) x.LineId = mLinea.LineNum).FirstOrDefault If oLinea IsNot Nothing Then RellenarLinea(mLinea, oLinea) End If Case EGuardadoTipoOperacion.Eliminar oLinea = oLineas.Where(Function(x) x.LineId = mLinea.LineNum).FirstOrDefault If oLinea IsNot Nothing Then oLineas.Remove(oLinea) End If End Select Next End If Destino.CDA_HOR1Collection = oLineas.ToArray End Sub
Teniendo esto, supuse que con documentos propios de SAP el proceso sería el mismo. Sí, a mi edad sigo siendo así de iluso.
En fin, si intentas hacer algo así con ofertas o pedidos de ventas e intentes eliminar y añadir filas en el mismo golpe, el resultado es un lío mayúsculo, modificándose líneas que no querías tocar y cosas por el estilo. Me puse a bucear por foros y notas de SAP, intentando descubrir qué estaba haciendo mal. La respuesta la encontré en un tema no relacionado en el que me fijé que el autor del ejemplo de solución forzaba la numeración de las líneas. Era un ejemplo de añadir un documento, no de edición. Pero como la diferencia más llamativa entre las líneas de objetos nativos de SAP y las líneas de UDO es que las primeras empiezan a numerarse en 0 y las segundas, en 1, pensé que por ahí podían ir los tiros y probé lo siguiente:
Private Sub RellenarLineas(origen As ICabecera, destino As Document) Dim oLineas As List(Of DocumentDocumentLine) Dim oLinea As DocumentDocumentLine Dim MaxLin As Long If destino.DocumentLines?.Length > 0 Then oLineas = destino.DocumentLines.ToList MaxLin = oLineas.Max(Function(x) x.LineNum) + 1 Else oLineas = New List(Of DocumentDocumentLine) MaxLin = 0 End If If origen.Detalles?.Any Then For Each mLinea In origen.Detalles Select Case mLinea.OperacionGuardado Case EGuardadoTipoOperacion.Nuevo oLinea = New DocumentDocumentLine Me.RellenarLinea(mLinea, oLinea) oLinea.LineNum = MaxLin oLinea.LineNumSpecified = True MaxLin += 1 oLineas.Add(oLinea) Case EGuardadoTipoOperacion.Modificar oLinea = oLineas.Where(Function(x) x.LineNum = mLinea.LineNum).FirstOrDefault If oLinea IsNot Nothing Then Me.RellenarLinea(mLinea, oLinea) End If Case EGuardadoTipoOperacion.Eliminar oLinea = oLineas.Where(Function(x) x.LineNum = mLinea.LineNum).FirstOrDefault If oLinea IsNot Nothing Then oLineas.Remove(oLinea) End If End Select Next End If destino.DocumentLines = oLineas.ToArray End Sub
¡Bingo!