Wednesday, September 3, 2025

Create custom service in d365foa for list type request using x++

 Request message:

{

  "PurchaseOrders": [

    {

      "PurchaseOrderId": "PO00078901",

      "VendorId": "VEND-1001",

      "VendorName": "ABC Raw Materials Pvt Ltd",

      "OrderDate": "2025-08-18",

      "ExpectedDeliveryDate": "2025-08-25",

      "Currency": "USD",

      "PurchaseOrderLines": [

        {

          "LineNumber": 1,

          "ProductId": "MAT-STEEL-001",

          "ProductName": "Mild Steel Rod 10mm",

          "OrderedQuantity": 500,

          "UnitOfMeasure": "KG",

          "UnitPrice": 2.50,

          "LineAmount": 1250.00,

          "WarehouseId": "WH-DELHI-01"

        },

        {

          "LineNumber": 2,

          "ProductId": "MAT-CEM-002",

          "ProductName": "Cement Grade A",

          "OrderedQuantity": 200,

          "UnitOfMeasure": "BAG",

          "UnitPrice": 5.00,

          "LineAmount": 1000.00,

          "WarehouseId": "WH-DELHI-01"

        }

      ]

    }

  ]

}

Custom service class:

public class DaxPurchaseOrderService

{

    [AifCollectionType("PurchaseOrders", Types::Class, classStr(DaxPurchaseOrderHeaderContract))]

    public str createPurchaseOrderJour(List PurchaseOrders)

    {

        ListEnumerator              poHeaderEnum   = PurchaseOrders.getEnumerator();

        DaxPurchaseOrderLinesEntity purchaseOrderLines;

        changecompany("DAT")

        {

            while (poHeaderEnum.moveNext())

            {

                DaxPurchaseOrderHeaderContract poHeaderContract = poHeaderEnum.current();

                List                          poLineList       = poHeaderContract.parmPurchaseOrderLines();

                ListEnumerator                poLineEnum       = poLineList.getEnumerator();

                try

                {

                    ttsbegin;

                    while (poLineEnum.moveNext())

                    {

                        checkRecords = true;

                        DaxPurchaseOrderLinesContract lineContract = poLineEnum.current();

                        purchaseOrderLines.clear();

                        purchaseOrderLines.PurchaseOrderNumber  = poHeaderContract.parmPurchaseOrderNumber();

                        purchaseOrderLines.VendorAccount        = poHeaderContract.parmVendorAccount();

                        purchaseOrderLines.OrderDate            = str2Date(poHeaderContract.parmOrderDate(), 213);

                        purchaseOrderLines.ExpectedDeliveryDate = str2Date(poHeaderContract.parmExpectedDeliveryDate(), 213);

                        purchaseOrderLines.CurrencyCode         = poHeaderContract.parmCurrencyCode();

                        purchaseOrderLines.ItemId               = lineContract.parmItemId();

                        purchaseOrderLines.OrderQty             = lineContract.parmOrderQty();

                        purchaseOrderLines.UnitPrice            = lineContract.parmUnitPrice();

                    }

                    ttscommit;

                }

                catch

                {

                    // handle exception (currently skipped)

                }

            }

        }

    }

}

Header contract:
[DataContract]
public class DaxPurchaseOrderHeaderContract
{
    str     purchaseOrderNumber;
    str     vendorAccount;
    str     orderDate;
    str     expectedDeliveryDate;
    str     currencyCode;
    List    purchaseOrderLines;
    str     warehouseIds;

    [DataMember("PurchaseOrderNumber")]
    public str parmPurchaseOrderNumber(str _purchaseOrderNumber = purchaseOrderNumber)
    {
        purchaseOrderNumber = _purchaseOrderNumber;
        return purchaseOrderNumber;
    }

    [DataMember("VendorAccount")]
    public str parmVendorAccount(str _vendorAccount = vendorAccount)
    {
        vendorAccount = _vendorAccount;
        return vendorAccount;
    }

    [DataMember("OrderDate")]
    public str parmOrderDate(str _orderDate = orderDate)
    {
        orderDate = _orderDate;
        return orderDate;
    }

    [DataMember("ExpectedDeliveryDate")]
    public str parmExpectedDeliveryDate(str _expectedDeliveryDate = expectedDeliveryDate)
    {
        expectedDeliveryDate = _expectedDeliveryDate;
        return expectedDeliveryDate;
    }

    [DataMember("CurrencyCode")]
    public str parmCurrencyCode(str _currencyCode = currencyCode)
    {
        currencyCode = _currencyCode;
        return currencyCode;
    }

    [DataMember("PurchaseOrderLines"), AifCollectionType("PurchaseOrderLines", Types::Class, classStr(DaxPurchaseOrderLineContract))]
    public List parmPurchaseOrderLines(List _purchaseOrderLines = purchaseOrderLines)
    {
        purchaseOrderLines = _purchaseOrderLines;
        return purchaseOrderLines;
    }

    [DataMember("WarehouseIds")]
    public str parmWarehouseIds(str_warehouseIds = warehouseIds)
    {
        warehouseIds = _warehouseIds;
        return warehouseIds;
    }
}

Lines contract :
[DataContract]
public class DaxPurchaseOrderLineContract
{
    ItemId      itemId;
    int         lineNumber;
    real        orderQty;
    AmountCur   unitPrice;

    [DataMember("ItemId")]
    public ItemId parmItemId(ItemId _itemId = itemId)
    {
        itemId = _itemId; 
        return itemId;
    }

    [DataMember("LineNumber")]
    public int parmLineNumber(int _lineNumber = lineNumber)
    {
        lineNumber = _lineNumber;
        return lineNumber;
    }

    [DataMember("OrderQty")]
    public real parmOrderQty(real _orderQty = orderQty)
    {
        orderQty = _orderQty;
        return orderQty;
    }

    [DataMember("UnitPrice")]
    public AmountCur parmUnitPrice(AmountCur _unitPrice = unitPrice)
    {
        unitPrice = _unitPrice;
        return unitPrice;
    }
}

Call API using x++ D365FO

 System.Net.HttpWebRequest    request; System.Net.HttpWebResponse   response; System.IO.Stream             dataStream; System.IO.StreamReade...