Replace \ Delegate Workflow User

With this piece of Code we can delegate Workflow from One User to another Using X++

Here I am taking example of Purchase Requistion


static void waj_replaceWorkflowUser(Args _args)
{
workflowtrackingstatustable workflowtrackingstatustable;
workflowtrackingtable workflowtrackingtable;
PurchReqTable purchreqTable;
WorkflowWorkItemTable workItem;
WorkflowStepTable workFlowStepTableSequence, workFlowStepTable;
WORKFLOWTRACKINGCOMMENTTABLE WORKFLOWTRACKINGCOMMENTTABLE;
purchreqTable = purchreqTable::findPurchReqId('PR-010454');
select workItem order by RecId desc
where workItem.RefTableId == tableNum(purchReqTable) &&
workItem.RefRecId == purchreqtable.recid &&
workItem.Status != WorkFlowWorkItemStatus::Completed &&
workItem.UserId == 's.Wajahat'; // slect user to replace
{
info(strFmt('%1', workItem.RefRecId));
}

WorkflowWorkItemActionManager::dispatchWorkItemAction(workItem,’Delegated’,’Ali’,WorkflowWorkItemActionType::Delegate,’PurchReqDelegate’,false);
}

Enable Modified by and Created by on ALL Parameters tables

Handy Code to have , Can be use to change any of the property of a table also just with the slightest change.

 

static void Waj_EnableProperties(Args _args)

{

SysDictTable dictTable,sysDictTable;
TreeNode node;
#AOT Name name;
TreeNode treeNode;
str indexName;
#Properties
;

treeNode = TreeNode::findNode(#TablesPath);
treeNode = treeNode.AOTfirstChild();

while (treeNode)

{
name = treeNode.AOTname();
sysDictTable = SysDictTable::newTableId(treeNode.applObjectId());

if ((sysDictTable.tableGroup() == tableGroup::Parameter ||
sysDictTable.tableGroup() == tableGroup::Group) &&
!sysDictTable.isMap() &&
!sysDictTable.isTmp() &&
!sysDictTable.isView() &&
sysDictTable.enabled())
{

node = SysDictTable.treeNode();
node.AOTsetProperty(#PropertyCreatedBy, #PropertyValueYes);

node.AOTsetProperty(#PropertyCreatedDateTime, #PropertyValueYes);
node.AOTsetProperty(#PropertyModifiedBy, #PropertyValueYes);
node.AOTsetProperty(#PropertyModifiedDateTime, #PropertyValueYes);

node.AOTsave();

node.treeNodeRelease();
node = null;

}

}

}

Create Ledger dimension from string values

1 – By using the below code one can create ledger dimesion recId using X++
Combination of Main Account and DimensionValue

container offsetAccount;

RefRecId ledgerDimension;

offsetAccount = [‘11850000’, ‘11850000’, 3, ‘Department’, ‘101’, ‘Customer’,‘Cus-101’, ‘Vendor’, ‘Vend-101’];
//[MainAccount,MainAccount, NoOfDimensions, DimensionName, value]

ledgerDimension = AxdDimensionUtil::getLedgerAccountId(offsetAccount);

2 – Create Ledger dimension from main account (default account) and default dimension

The DimensionDefaultingService::serviceCreateLedgerDimension() method can be used to create ledger dimension from main account and default dimension.

JournalTrans.LedgerDimension = DimensionDefaultingService::serviceCreateLedgerDimension(_defaultAccount,
JournalTrans.DefaultDimension);

Create Default dimension using x++

The following job will get a DimensionAttributeValueSet record ID base on the a set of dimension values.

 

static void CreateDefaultDimensions(Args _args)
{
PurchTable purchTable;
DimensionAttributeValueSetStorage valueSetStorage = new DimensionAttributeValueSetStorage();
DimensionDefault result;

int i;
DimensionAttribute dimensionAttribute;
DimensionAttributeValue dimensionAttributeValue;

// Note that “Item” is not one of the default dimension,
// but DimensionAttributeValueSetStorage will handle it gracefully
container conAttr = [“Project”, “Vendor”]; // Dimensions
container conValue = [“1001”, “Ven-0046”]; //  respective Values
str dimValue;

purchTable = purchTable::find(‘000471’);

for (i = 1; i <= conLen(conAttr); i++)
{
dimensionAttribute = dimensionAttribute::findByName(conPeek(conAttr,i));

if (dimensionAttribute.RecId == 0)
{
continue;
}

dimValue = conPeek(conValue,i);

if (dimValue != “”)
{
// The last parameter is “true”. A dimensionAttributeValue record will be created if not found.
dimensionAttributeValue =
dimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,dimValue,false,true);

// Add the dimensionAttibuteValue to the default dimension
valueSetStorage.addItem(dimensionAttributeValue);
}
}

result = valueSetStorage.save();
purchTable.selectForUpdate(true);
ttsBegin;
purchTable.DefaultDimension = result;
purchTable.doUpdate();
ttsCommit;
}

Get Comments of a Workflow

We can use this sample code to get the workflow comments on particular Record. Project budget is my desired table  . you can replace ProjBudget to any other table on which you want to get the entered comments.

workflowcomment

while select WORKFLOWTRACKINGSTATUSTABLE where WORKFLOWTRACKINGSTATUSTABLE.ContextRecId == projBudget.RecId  //
&& WORKFLOWTRACKINGSTATUSTABLE.ContextTableId == tableNum(ProjBudget)
{

while select WORKFLOWTRACKINGTABLE where WORKFLOWTRACKINGTABLE.WorkflowTrackingStatusTable == WORKFLOWTRACKINGSTATUSTABLE.RecId
{
while select WORKFLOWTRACKINGCOMMENTTABLE
where WORKFLOWTRACKINGCOMMENTTABLE.WorkflowTrackingTable == WORKFLOWTRACKINGTABLE.RecId

{

}

}

Go to origin \ Custom button on Info

Just a quick code to add a button on InfoLog to facilitate user to go directly on the respective message record.

OutPut: 

rfq-img

 

Code :

img-2

 

SysInfoAction_MenuFunction        sysInfoAction; //Class which we have to use to create a Button.
purchRFQCaseTable       purchRFQCaseTable; // Declaration of buffer
purchRFQCaseTable = purchRFQCaseTable::find(‘RFQ-0001’);

sysInfoAction = SysInfoAction_MenuFunction::newMenuItem(menuitemDisplayStr(PurchRFQCaseTable),MenuItemType::Display); // here we create a button Link with the menu Item of the form to open on click event
sysInfoAction.parmCallerBuffer(purchRFQCaseTable); //passing buffer on the form
info (strfmt(“@SYS107925″, purchRFQCaseTable.rfqCaseId),”, sysInfoAction); // creating info with desired button

 

 

 

Write/Create Files into folder during Batch jobs

A sample code to write data into specified directory. I have used TEXTIO  here because my requirment is to run that from batch and i have used sys Operational framework  .

 

 

TextIo textIOWrite;
str fileLine, headerFileLine, fileName, filePath;
//Creating the header of my file

headerFileLine = strFmt(“%1|%2|%3|%4|%5|%6|%7|%8|%9|%10|%11|%12|%13|%14|%15|%16|%17|%18|%19|%20|%21|%22|%23|%24”,
‘client’, ‘company’, ‘keycode’, ‘order_number’, ‘order_date’, ‘po_number’, ‘po_date’, ‘international’, ‘ship_method’, ‘first_name’, ‘last_name’ ,’addr1′,
‘addr2′ ,’addr3′ ,’city’ ,’state’ ,’zip’ ,’country’ ,’ship_date’ ,’comments’ ,’item’, ‘description’ ,’size’ , ‘qty’);

//Insert logic here for data manupilation

// Inserting data into my FileLine
fileLine = strFmt(“%1|%2|%3|%4|%5|%6|%7|%8|%9|%10|%11|%12|%13|%14|%15|%16|%17|%18|%19|%20|%21|%22|%23|%24″,
’56’, countryName , ‘DEFAULT’, salesTable.SalesId, salesLine.ShippingDateRequested, SalesTable.CustomerRef, SalesLine.ReceiptDateRequested,
Country, SalesLine.DlvMode,’ ‘, SalesLine.DeliveryName, addr1, addr2, addr3, city , state , zip, logisticsPostalAddress.CountryRegionId,
SalesLine.ShippingDateRequested, notes, salesLine.ItemId, SalesLine.itemName(), Size::findbyRecId(InventTable::find(salesLine.ItemId).Size).Name,SalesLine.SalesQty);

//After creating the header and data line i am creating my file now
fileName = ‘MyFile’ + ‘.csv’; // I am creating CSV files here

filePath = SysFileStoreParameters::find().OutgoingDirectory; // I have created a parameter to save my folder location in system parameters and reading data from that custom parameter

if (filePath == ”)
{
throw error(‘File path no setup.’);
}

if (subStr(filePath, strLen(filePath)-1, 1) != @”\”)
{
filePath = filePath +@”\”;
}

filePath = filePath+fileName;

languageId = SystemParameters::find().SystemLanguageId;

FileIOPermission = new FileIOPermission(filePath, “RW”);
FileIOPermission.assert();

textIOWrite = new TextIo(filePath , “W”, 20127);

textIOWrite.write(headerFileLine);
textIOWrite.write(fileLine);