Skip to Content
Author's profile photo R. Pol

SAP HANA SL, Solution if your code doesn’t create an Invoice based on a Delivery

Hi,

A while back i started developing with HANA Service Layer and found a very useful blog from Trinidad with some sample code (https://blogs.sap.com/2015/07/15/how-to-consume-service-layer-odata-services-from-net-via-wcf/)…

At some point i wanted to create a Sales Order based on an input file and create a Delivery based on that Sales Order and finally an Invoice based on that Delivery. The first 2 steps went without a problem, but when i wanted to create the Invoice, i got an error…

Thanks to SAP support i finally found out what the issue was. One of the functions supplied by SAP support was different from the sample code. Here is the function that worked for me:

/// <summary>
/// Create new ODataComplexValue from the old, to discard all null/zero values
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
private ODataComplexValue RebuildComplexValue(ODataComplexValue source)
{
    ODataComplexValue newVal = new ODataComplexValue();
    newVal.TypeName = source.TypeName;

    List<ODataProperty> complexSons = source.Properties.ToList();

    //Filter to get new list
    List<ODataProperty> filteredSons = new List<ODataProperty>();
    foreach (ODataProperty prop in complexSons)
    {
        PropertyType retType = GetPropertyType(prop);
        switch (retType)
        {
            case PropertyType.SimpleEdmx:
                {
                    if (null != prop.Value)
                    {
                        filteredSons.Add(prop);
                    }
                }
                break;

            case PropertyType.ComplexType:
                {
                    //Recursively
                    ODataComplexValue comx = RebuildComplexValue((ODataComplexValue)prop.Value);
                    if (comx.Properties.Count() > 0)
                    {
                        prop.Value = comx;
                        filteredSons.Add(prop);
                    }
                }
                break;

            case PropertyType.Collection:
                {
                    ODataCollectionValue coll = RebuildCollectionValue((ODataCollectionValue)prop.Value);
                    List<ODataComplexValue> listSubs = (List<ODataComplexValue>)coll.Items;
                    if (listSubs.Count > 0)
                    {
                        prop.Value = coll;
                        filteredSons.Add(prop);
                    }
                }
                break;

            default:
                break;
        }
    }

    //Re-Assign sons
    newVal.Properties = filteredSons;

    return newVal;
}

The part from “case PropertyType.SimpleEdmx:” is different in the original sample code, here is the original code:

case PropertyType.SimpleEdmx:
    {
        if (null != prop.Value)
        {
            if (prop.Value.GetType().Name == "Int32")
            {
                //Check the value now.
                bool bInclude = false;
                try
                {
                    //TODO: You cannot simply do this, potential bugs there maybe.
                    //Use your own logics the determine if need to ignore ZEORs or not.
                    int val = Convert.ToInt32(prop.Value);
                    bInclude = (0 != val);
                }
                catch (Exception)
                {
                }

                if (bInclude)
                    filteredSons.Add(prop);
            }
            else
                filteredSons.Add(prop);
        }
    }
    break;

Hopefully i can prevent some headaches for other people with this information…

Have a good day…

Ruben

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.