Thursday, August 10, 2023

Create Transfer order using X++

public void createTransferOrder(InventLocationId _inventLocationIdFrom,InventLocationId  _inventLocationIdTo, TransDate _deliveryDate)
    {
        inventTransferTable.clear();
        inventTransferTable.initValue();

        InventTransferId transferOrderId = InventTransferTable::numberSeq().num();
        inventTransferTable.TransferId = transferOrderId;

        inventTransferTable.InventLocationIdFrom = _inventLocationIdFrom;
        inventTransferTable.modifiedField(fieldNum(InventTransferTable, InventLocationIdFrom));
        inventTransferTable.InventLocationIdTo = _inventLocationIdTo;
        inventTransferTable.modifiedField(fieldNum(InventTransferTable, InventLocationIdTo));
        inventTransferTable.InventLocationIdTransit = InventLocation::find(inventTransferTable.InventLocationIdFrom).InventLocationIdTransit;
        inventTransferTable.DeliveryDateControlType = SalesDeliveryDateControlType::None;
        inventTransferTable.ShipDate = _deliveryDate;
        inventTransferTable.ReceiveDate = _deliveryDate;

        inventTransferTable.initFromAddress();
        inventTransferTable.initToAddress();
        inventTransferTable.AutoReservation = true;

        if (inventTransferTable.validateWrite())
        {
            inventTransferTable.insert();
        }
        else
        {
            throw error("@SCM:FailTransferOrder");
        }
    }

    
    /// <summary>
    /// Create transfer order lines
    /// </summary>
    /// <param name = "_currPurchLine">PurchLine table buffer</param>
    /// <param name = "_inventTransferTable">Transfer order header buffer</param>
    public void createTransferLine(PurchLine _currPurchLine, InventTransferTable _inventTransferTable)
    {
        InventTransferLine currInventTransferLine;
        
        currInventTransferLine.initValue();
        
        currInventTransferLine.ItemId		= _currPurchLine.ItemId;

        currInventTransferLine.initFromInventTable(InventTable::find(_currPurchLine.ItemId));
        currInventTransferLine.initFromInventTableModule(InventTableModule::find(currInventTransferLine.ItemId, ModuleInventPurchSales::Invent));
        currInventTransferLine.initFromInventTransferTable(_inventTransferTable, true);

        currInventTransferLine.inventdimid	= _currPurchLine.InventDimId;
        
        currInventTransferLine.QtyTransfer = _currPurchLine.QtyOrdered;
        currInventTransferLine.QtyRemainReceive = currInventTransferLine.QtyTransfer;
        currInventTransferLine.QtyRemainShip    = currInventTransferLine.QtyTransfer;

        currInventTransferLine.DeliveryDateControlType = SalesDeliveryDateControlType::None;

        TransDate shipdate = this.getShipDate(_currPurchLine);
       
        currInventTransferLine.ShipDate = shipdate;
        InventItemInventSetup inventItemInventSetup = InventItemInventSetup::find(currInventTransferLine.itemId, currInventTransferLine.inventDimId);

        if (inventItemInventSetup.LeadTime)
        {
            currInventTransferLine.ReceiveDate =  currInventTransferLine.ShipDate + inventItemInventSetup.LeadTime;
        }
        else
        {
            currInventTransferLine.modifiedField(fieldNum(InventTransferLine, ShipDate));
        }

        currInventTransferLine.LineNum = _currPurchLine.LineNumber;

        
        if (currInventTransferLine.validateWrite())
        {
            currInventTransferLine.insert();

            info(strFmt("@SCM:CreateTOfromSalesLine", currInventTransferLine.TransferId, currInventTransferLine.ItemId));
           
        }
        else
        {
            throw error(strFmt("@SCM:FailedToCreateTtransferLineFromSalesLine", currInventTransferLine.TransferId, currInventTransferLine.ItemId));
        }
    }

Select Min and Max dates from lines

/// <summary>
    ///  set date for inventtransfer header
    /// </summary>
    /// <param name = "_inventTransferTable">
    /// InventTransferTable buffer
    /// </param>
    /// <param name = "_purchId">
    /// Purchase order number
    /// </param>
    public void setDatesInventTransferTable(InventTransferTable _inventTransferTable, PurchIdBase _purchId)
    {
        InventTransferLine transferLine;

        _inventTransferTable.reread();
        _inventTransferTable.selectForUpdate(true);

        select minof(ShipDate), maxof(ReceiveDate) from transferLine
                                where transferLine.TransferId == _inventTransferTable.TransferId;

        _inventTransferTable.ShipDate = transferLine.ShipDate;
        _inventTransferTable.ReceiveDate =  transferLine.ReceiveDate;
        _inventTransferTable.PurchaseOrderId_DIS =  _purchId;

        _inventTransferTable.update();
    }

Retrieves the format for data regarding date and time in Date format - ISO 8601

str DeliveryDate = RetailENInfo::formatDatetimeData(purchPurchaseOrderTmp.DeliveryDate, "sv");

HTML formatting in SSRS report using X++

  purchPurchaseOrderTmpLoc.Name   = inventTable.itemName();
        if (externalItemFreeTxt)
        {
            purchPurchaseOrderTmpLoc.Name   = strFmt('%1 <br />', purchPurchaseOrderTmpLoc.Name);
            purchPurchaseOrderTmpLoc.Name += strFmt('<i> %1: %2 </i>', "@SYS342305", externalItemFreeTxt);
        }
        if (barcode)
        {
            purchPurchaseOrderTmpLoc.Name   = strFmt('%1 <br />', purchPurchaseOrderTmpLoc.Name);
            purchPurchaseOrderTmpLoc.Name += strFmt('<i> %1: %2 </i>', "@SYS331679", barcode);
        }
Then in ssrs report designer enable html markup in the text box

DataEntity import Dynamic field mapping X++

using JSONTOXMLConvert;
Public class CommonDataEntityImportService
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name = "Entities"></param>
    /// <returns></returns>
    public CommonDataEntityImportResponseContract importData(Newtonsoft.Json.Linq.JObject    Entities)
    {
        // Define XML Document and its nodes
        XmlDocument     doc;
        XmlNodeList     xmlMainNodeList;
        XmlNodeList     xmlChildNodeList;
        XmlElement      nodeRoot;
        XmlElement      nodeParent;
        XMLParseError   xmlError;
        // Define temporary variables
        int i, j;
        str response;
        Set setResponsetext = new Set(Types::String);

        try
        {
            //passsing and converting JSOn to XML
            
            str xml = Utilities::ConvertToXML(Entities);

            doc = new XmlDocument();
            doc.loadXml(xml);

            // Verify XML Document Structure
            xmlError  = doc.parseError();
            if(xmlError && xmlError.errorCode() != 0)
            {
                throw error(strFmt("XML Error: %1", xmlError.reason()));
            }

            // Get the root element and its child nodes
            nodeRoot = doc.firstChild();
            xmlMainNodeList = nodeRoot.childNodes();

            //looping through all the Parent nodes
            for (i=0; i < xmlMainNodeList.length(); i++)
            {
                Common          common;
                SysDictTable    dictTable;
                SysDictField    dictField;
                str             responseText =  strMin();

                nodeParent          = xmlMainNodeList.item(i);
                xmlChildNodeList    = nodeParent.childNodes();
                str parentNodeName  = nodeParent.name();

                XmlElement  lineNumber;
                XmlElement  orderNumber;
                XmlElement  dataAreadid;

                switch (parentNodeName)
                {
                    case 'PurchaseOrderHeader':
                        dictTable           = new SysDictTable(tableName2Id(tableStr(PurchPurchaseOrderHeaderEntity)));
                        common              = dictTable.makeRecord();
                        orderNumber         = nodeParent.selectSingleNode(fieldStr(PurchPurchaseOrderHeaderEntity, PurchaseOrderNumber));
                        dataAreadid         = nodeParent.selectSingleNode(fieldStr(PurchPurchaseOrderHeaderEntity, DataAreaId));
                        responseText        = strFmt("Purchase order %1", orderNumber.text());

                        select forupdate common
                            where common.(fieldName2id(common.TableId, 'PurchaseOrderNumber')) == orderNumber.text() &&
                             common.(fieldName2id(common.TableId, 'DataAreaId')) == dataAreadid.text();

                        break;
                    case 'PurchaseOrderLinesV2':
                        dictTable           = new SysDictTable(tableName2Id(tableStr(PurchPurchaseOrderLineV2Entity)));
                        common              = dictTable.makeRecord();
                        lineNumber          = nodeParent.selectSingleNode(fieldStr(PurchPurchaseOrderLineV2Entity, LineNumber));
                        orderNumber         = nodeParent.selectSingleNode(fieldStr(PurchPurchaseOrderLineV2Entity, PurchaseOrderNumber));
                        dataAreadid         = nodeParent.selectSingleNode(fieldStr(PurchPurchaseOrderLineV2Entity, DataAreaId));
                        responseText        = strFmt("Purchase order %1", orderNumber.text());
                       
                        select forupdate common
                        where common.(fieldName2id(common.TableId, 'PurchaseOrderNumber')) == orderNumber.text() &&
                            common.(fieldName2id(common.TableId, 'LineNumber')) == str2Int64(lineNumber.text()) &&
                            common.(fieldName2id(common.TableId, 'DataAreaId')) == dataAreadid.text();

                        break;
                }
                
                //looping through all the child nodes
                for (j=0; j < xmlChildNodeList.length(); j++)
                {
                    XmlElement nodeChild = xmlChildNodeList.item(j);

                    str value  = nodeChild.text();

                    dictField = dictTable.fieldObject(fieldName2Id(dictTable.id(), nodeChild.name()));
        
                    if(dictField)
                    {
                        switch (dictField.baseType())
                        {
                            case Types::Int64 :
                                common.(fieldName2Id(common.TableId, nodeChild.name())) = str2Int64(value);
                                break;
                            case Types::Integer :
                                common.(fieldName2Id(common.TableId, nodeChild.name())) = str2Int(value);
                                break;
                            case Types::Date :
                                common.(fieldName2Id(common.TableId, nodeChild.name())) = str2Date(value,321);
                                break;
                            case Types::Real :
                                common.(fieldName2Id(common.TableId, nodeChild.name())) = str2Num(value);
                                break;
                            default :
                                common.(fieldName2Id(common.TableId, nodeChild.name())) = value;
                                break;
                        }
                    }
                
                }
                ttsbegin;
                if (common.RecId)
                {
                    common.update();
                    response = orderNumber.text();
                }
                else
                {
                    common.insert();
                    response = orderNumber.text();
                }
                ttscommit;

            }

            return this.formatResponseToJSON(response);
            
        }
        catch(Exception::CLRError)
        {
            throw Error("CLRError : DLL Error");
        }
        catch(Exception::Error)
        {
            throw Error("unknown Error");
        }
        catch(Exception::DuplicateKeyException)
        {
            throw Error("DuplicateKeyException: Record already exists");
        }
    }

    /// <summary>
    /// generate JSON response
    /// </summary>
    /// <param name = "_set"></param>
    /// <returns></returns>
    public HFGCommonDataEntityImportResponseContract formatResponseToJSON(PurchId _poNum)
    {
        HFGCommonDataEntityImportResponseContract responseContract = new HFGCommonDataEntityImportResponseContract();
        responseContract.parmResponse(_poNum);

        return responseContract;
    }

}

==============

response contarct
[DataContractAttribute]
class CommonDataEntityImportResponseContract
{
    PurchId  response;
    
    [DataMemberAttribute('PurchaseOrderNumber')]
    public PurchId parmResponse(PurchId _response = response)
    {
        response = _response;
        return response;
    }

}
========
JSON payload
{
    "Entities": {
        "PurchaseOrders": [
            {
                "PurchaseOrderHeader": [
                    {
                        "DataAreaId": "100",                        
                        "PurchaseOrderNumber": "6100001105",
                        "OrderVendorAccountNumber": "60000016",
                        "RequestedDeliveryDate": "2023-06-09",
                        "VendorOrderReference": "SO000609C",
                        "ReceivingWarehouseId": "DC01"
                    }
                ],
                "PurchaseOrderLinesV2": [
                    {
                        "DataAreaId": "100",   
                        "LineNumber": 6.00,                     
                        "ItemNumber": "44573054",
                        "ProductConfigurationId": "44573054C001",
                        "OrderedPurchaseQuantity": 1,
                        "RequestedDeliveryDate": "2023-06-09",
                        "ReceivingWarehouseId": "DC01",
                        "PurchasePrice": 4,
                        "PurchaseOrderNumber": "6100001105"
                    }
                ]
            }
        ]
    }
}

======
JSON to XML convesrion using C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Xml.Linq;

namespace JSONTOXMLConvert
{
    public class Utilities
    {
        public static string ConvertToXML(Newtonsoft.Json.Linq.JObject myJObject)
        {
            string json = myJObject.ToString(Newtonsoft.Json.Formatting.None);
            //if an empty string is passed, return empty string without conversion
            if (string.IsNullOrEmpty(json))
                return string.Empty;
            //if invalid json is passed, throw error.
            ValidateJSON(json);
            //Convert Json to XML
            XDocument xmlDoc = JsonConvert.DeserializeXNode(json);
            return xmlDoc.ToString();
        }
        public static void ValidateJSON(string json)
        {
            try
            {
                var jsonObject = JObject.Parse(json);
            }
            catch (Exception ex)
            {
                throw new InvalidCastException("Provided json is not valid.", ex);
            }
        }
    }
}

JumpRef in form extension X++

class PurchTableForm_EventHandler
{
    /// <summary>
    /// JumpRef mthod overrride for form control
    /// </summary>
    /// <param name = "sender"></param>
    /// <param name = "e"></param>
    [FormEventHandler(formStr(PurchTable), FormEventType::PostRun),SuppressBPWarning('BPParameterNotUsed', 'Parameter required')]
    public static void PurchTable_OnPostRun(xFormRun sender, FormEventArgs e)
    {
        FormStringControl   control = sender.design().controlName(formControlStr(PurchTable, TransferOrderId));
        control.registerOverrideMethod(methodStr(FormStringControl, jumpRef), methodStr(PurchTableForm_Extension, jumpRef), sender);
    }

}

/// <summary>
/// Extension for PurchTable form
/// </summary>
[ExtensionOf(formstr(PurchTable))]
final class PurchTableForm_Extension
{
    /// <summary>
    /// JumpRef override method
    /// </summary>
    /// <param name = "_formControl">form controlId</param>
    public void jumpRef(FormControl _formControl)
    {
        MenuFunction	menuFunction;
        Args        	args = new Args();
        PurchTable      purchTable  =_formControl.formRun().dataSource(formDataSourceStr(PurchTable,PurchTable)).cursor() as PurchTable;

        if(purchTable.TransferOrderId)
        {
            InventTransferTable  InventTransferTable = InventTransferTable::find(purchTable.TransferOrderId);

            args.record(InventTransferTable);
            args.lookupRecord(InventTransferTable);

            menuFunction = new MenuFunction(menuitemDisplayStr(InventTransferOrder), MenuItemType::Display);

            menuFunction.run(args);
        }
    }

}

Table browser URL in D365FO

Critical Thinking icon icon by Icons8