Tuesday, August 16, 2016

Add/Remove Role to User through X++ code AX2012

Hi guys. We had a requirement where I had to provide SysAdmin role to the current user for the task which he is performing and once it is done then the role had to be removed. As ever google came to help big time and finally my code is ready:

Method to add role:

private void grantAdminRole()
{
    SecurityRole        role;
    SecurityUserRole    userRole;
    boolean             added;
    UserInfo            userInfo;

    select role where role.Name == 'System Administrator';

    select * from userRole
        where userRole.SecurityRole == role.RecId &&
            userRole.User == curUserId();

    if (!userRole || (userRole.AssignmentStatus != RoleAssignmentStatus::Enabled))
    {
        userRole.User = curUserId();
        userRole.SecurityRole = role.RecId;
        userRole.AssignmentMode = RoleAssignmentMode::Manual;
        userRole.AssignmentStatus = RoleAssignmentStatus::Enabled;
        SecuritySegregationOfDuties::assignUserToRole(userRole, null);
    }
}


Method to remove the role from user:

private void revokeAdminRole()
{
    fieldName                           userId;
    SysSecTreeRoles                     roleTree;
    SecurityUserRole                    securityUserRole;
    OMUserRoleOrganization              org;
    SecurityUserRoleCondition           condition;
    SecuritySegregationOfDutiesConflict conflict;
    SecurityRole                        role;

    ttsbegin;

    select role where role.Name == 'System Administrator';

    delete_from condition
        exists join securityUserRole
        where condition.SecurityUserRole == securityUserRole.RecId && securityUserRole.User == curUserId() && securityUserRole.SecurityRole == role.RecId;

    select OMInternalOrganization, SecurityRole from org where org.User == curUserId() && org.SecurityRole == role.RecId;

    if (org.SecurityRole)
    {
        EePersonalDataAccessLogging::logUserRoleChange(org.SecurityRole, org.omInternalOrganization, curUserId(), AddRemove::Remove);
    }

    delete_from org where org.User == curUserId() && org.SecurityRole == role.RecId;

    delete_from conflict where conflict.User == curUserId() && ((conflict.ExistingRole == role.RecId) || (conflict.NewRole == role.RecId));

    //<GEEEE>
    EePersonalDataAccessLogging::logUserRoleChange(role.RecId, 0, curUserId(), AddRemove::Remove);
    //</GEEEE>

    delete_from securityUserRole where securityUserRole.User == curUserId() && securityUserRole.SecurityRole == role.RecId;

    ttscommit;

}

Friday, July 8, 2016

Update ProductDimension, StorageDimension & SearchName of Items/Products

We had a requirement to update ProductDimension and StorageDimension of all the items. I wrote 2 jobs for the same. Below are those:

Update ProductDimension:
static void UpdateProductDimension(Args _args)
{
    EcoResProduct                       ecoResProduct;
    EcoResProductDimensionGroupProduct  ecoResProductDimensionGroupProduct;
 
    while select ecoResProduct
        where ecoResProduct.RecId != 0
    {
        ecoResProductDimensionGroupProduct.initFromProduct(ecoResProduct);
        ecoResProductDimensionGroupProduct.ProductDimensionGroup = 'NameHere';
        ecoResProductDimensionGroupProduct.insert();
    }
 
    info("Done");
}

Update StorageDimension:
static void Job48(Args _args)
{
    EcoResProduct                       ecoResProduct;
    EcoResStorageDimensionGroup         ecoResStorageDimensionGroup;
    EcoResStorageDimensionGroupProduct  ecoResStorageDimensionGroupProduct;
    EcoResStorageDimensionGroupItem     ecoResStorageDimensionGroupItem;
    InventTable                         inventTable;
 
    select Name from ecoResStorageDimensionGroup
        where ecoResStorageDimensionGroup.Name == 'NameHere';
 
    while select ecoResProduct
        join inventTable
        where ecoResProduct.RecId == inventTable.Product
    {
        ecoResStorageDimensionGroupItem.initValue();
        ecoResStorageDimensionGroupItem.ItemDataAreaId = inventTable.dataAreaId;
        ecoResStorageDimensionGroupItem.ItemId = inventTable.ItemId;
        ecoResStorageDimensionGroupItem.StorageDimensionGroup = ecoResStorageDimensionGroup.RecId;
        ecoResStorageDimensionGroupItem.insert();
    }
 
    info("Done");
}

Update SearchName:
static void Job48(Args _args)
{
    EcoResProductTranslation    ecoResProductTranslation;
    InventTable                 inventTable;
    EcoResProduct               ecoResProduct;
 
    update_recordset inventTable
    setting NameAlias = ecoResProductTranslation.Name
    join ecoResProduct
    where ecoResProduct.RecId == inventTable.Product
    join ecoResProductTranslation
    where ecoResProductTranslation.Product == ecoResProduct.RecId
    && ecoResProductTranslation.Name == 'Bentinck One Seater Sofa in Provincial Teak Finish with Mudramark';
 
    info("Done");
}

ReferenceSource: http://fandyax.blogspot.in/2013/04/how-to-using-x-create-item-in.html


Checklist can't be skipped Ax2012

Today I faced an issue where I had installed a Hotfix and completed the checklist but even after that the checklist kept popping up.

Then I came to know about the table which controls it. It's named "ReleaseUpdateConfiguration" and there is a field "MinorUpgrade" which will be checked. So in this case we need to uncheck it and the magic happens!

Source: http://yetanotherdynamicsaxblog.blogspot.in/2014/03/skip-modelstore-has-been-modified-dialog.html

Monday, June 13, 2016

Could not load file or assembly 'Microsoft.ReportingServices.RdlObjectModel, Culture=neutral, PublicKeyToken=' or one of its dependencies. Access is denied. ax2012

Today I faced a new error while running reports in AX. "Could not load file or assembly 'Microsoft.ReportingServices.RdlObjectModel, Culture=neutral, PublicKeyToken=' or one of its dependencies. Access is denied. ax2012"

The solution to this is to give permission to all the users on the .NET folder:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files” ( Modify the framework version, root directory etc according to your environment. )

Goto folder properties, select security, select "USERS" and grant full control. Press Apply and OK.


Credit: https://blogs.msdn.microsoft.com/sayanghosh/2007/04/21/solution-to-could-not-load-file-or-assembly-or-one-of-its-dependencies-access-is-denied/

Sunday, May 8, 2016

Change design of Document report

I had to change the design of PO report today and I followed the usual way of mentioning my design in the controller class.
But then realized that it's not working and found that I need to make a change of design from the "FormLetterReport" class.

There is a method named "loadPrintSettings" where you can mention the design change for these document report like PO, GRN etc.

Wednesday, April 27, 2016

Filter on display method using context method

You may find a lot of codes for the same purpose but the one which worked flawlessly for me is written below:

Write the below code in the executeQuery method of the root DS:

public void executeQuery()
{
super();

if(!queryObj)
{
queryObj = true;
existQuery = new Query(this.query());
existQuery.saved();
remFilQuery = new Query();
remFilQuery = existQuery;
remFilQuery = existQuery.makeCopy();
}
}

Now the context method in the display method control:
public void context()
{
int selectedMenu;
formrun fr;
Args ag;
Name strtext;
str filSel = ”;
querybuilddataSource qb1, qb2, qb3;
queryrun qr;
query q, q2;
PopupMenu menu = new PopupMenu(element.hWnd());
int a = menu.insertItem(‘Filter by field’);
int b = menu.insertItem(‘Filter by selection’);
int c = menu.insertItem(‘Clear’);
;

selectedMenu = menu.draw();
switch (selectedMenu)
{
case a: //Filter by field
ag = new args(‘SysformSearch’);
fr = new formrun(ag);
fr.run();
fr.wait();

//Reading User entered value for filter process
strtext = fr.design().controlName(‘FindEdit’).valueStr();
//strtext = ‘”‘ + fr.design().controlName(‘FindEdit’).valueStr() + ‘”‘;
if(strtext)
{
//Creating a query for filter
q = new Query(InventSerial_ds.query());
// existQuery = InventJournalTrans_ds.query();

qb1 = q.dataSourceTable(tablenum(InventSerial));

qb2 = qb1.addDataSource(TableNum(EcoResProduct));
qb2.addLink(FieldNum(InventSerial,ItemId),FieldNum(EcoResProduct,DisplayProductNumber));

qb3 = qb2.addDataSource(tableNum(EcoResProductTranslation));
qb3.relations(true);

qb3.addRange(fieldNum(EcoResProductTranslation, Name)).value(strtext);
qb3.addRange(fieldNum(EcoResProductTranslation, LanguageId)).value(infolog.language());

InventSerial_ds.query(q);
InventSerial_ds.executeQuery();

}

break;

case b: // Filter By Selection3

q = new Query(InventSerial_ds.query());

qb1 = q.dataSourceTable(tablenum(InventSerial));

qb2 = qb1.addDataSource(TableNum(EcoResProduct));
qb2.addLink(FieldNum(InventSerial,ItemId),FieldNum(EcoResProduct,DisplayProductNumber));

qb3 = qb2.addDataSource(tableNum(EcoResProductTranslation));
qb3.relations(true);

filSel = ‘”‘ + ItemDesc.valueStr() + ‘”‘;

qb3.addRange(fieldNum(EcoResProductTranslation, Name)).value(filSel);
qb3.addRange(fieldNum(EcoResProductTranslation, LanguageId)).value(infolog.language());

InventSerial_ds.query(q);
InventSerial_ds.executeQuery();

break;

case c : // Remove Filter

InventSerial_ds.query(remFilQuery);
InventSerial_ds.executeQuery();

break;

Default:
break;
}
}

Credits: https://msddax.wordpress.com/2014/11/29/filter-on-the-display-method-using-context-method/

Tuesday, April 26, 2016

Multiple designs in Print Mgmt

I had to attach a new design to the Product Receipt report (PurchPackingSlip) which would run through a new menu item.

I tried to override the design by checking the calling menu item in the controller class but it always seemed to be picking from Print Management setup. Then I came across this:

If you have new formats for Sales/Purchase/Quotation confirmation/Picking/Packing/Invoice..., following these steps :

Step1. Create new Design for report under visual studio.

Step2. Add code to method:
\Data Dictionary\Tables\PrintMgmtReportFormat\Methods\populate
Add code  before TTSCOMMIT:
addOther(PrintMgmtDocumentType::SalesOrderPackingSlip, ssrsReportStr(SalesPackingSlip, ReportUD), ssrsReportStr(SalesPackingSlip, ReportUD), #NoCountryRegionId);    

Step 3. Choose you new format under:
AR -> setup -> form setup -> Print management -> Sales order Packing slip original -> report format to  SalesPackingslip.ReportUD

Step 4.
New Report design can be executed from use Print management from Inquiry journal forms or during posting by selecting Print management destination.

Step 5. (Optional)
In case: the report still keep original design, add this code to class TradeDocumentReportController in method outputReport:
//original menu item or your new menu item
if(args.menuItemName() == menuitemOutputStr(SalesPackingSlipOriginal))
{
formLetterReport.getCurrentPrintSetting().parmReportFormatName(ssrsReportStr(SalesPackingSlipOriginal, ReportUD));
}

Credits: http://axvuongbao.blogspot.in/2014/04/how-to-add-multiple-report-design-under.html