My 2p about ERP Solutions, Information Worker Solutions and other software products (mainly Microsoft Dynamics AX and Microsoft SharePoint).

28 February 2013

About setting up case e-mail templates

Introduction

To set up a case e-mail template, first you create a template and then you open the e-mail editor to set up the predefined contents of e-mail messages that are based on the template.

The predefined contents consist of merge data and links that can be inserted in the template.

The merge data is a set of data that provides details on the case in the e-mail message.

Merge-data overview

The following merge-data elements can be added in the e-mail template. The merge-data elements can be used to inform the user about various aspects of the case.

HTML merge-data element Information displayed in e-mail message
%CaseId% The identification number assigned to the case
%CaseDescription% A description of the case
%CaseSourceName% The name of the party record that the case is created for
%CaseMemo% Additional notes about the selected  case

 

Link the e-mail template to the case category

 

Start sending mails from your Cases, some data of the case will be merged into the generated e-mail message.


Continue reading......

by Patrik Luca 1 comments

30 January 2013

Wrong email displayed for alert rules in Dynamics AX 2009

Problem description

When creating or modifying alert rules, the e-mail shows always the email
of the current user, in stead of the email of the user for whom the alert rule
is valid. This problem is fixed in Dynamics AX 2012.

Solution

Some X++ modifications are needed in two Forms.

Form EventCreateRule, method modified on Field EventRule.UserId:

public void modified()
{
super();

// BEGIN
eventRule_SendEmailAddress.text(
SysUserInfo::find(EventRule.UserId).Email);
// END
}


Form EventRule, method setControlsActive on DataSource EventRule:



...
else if (!canShowPopUpCheckBox)
{
alertMeBy.visible(true);
eventRule_ShowPopUp.visible(false);
eventRule_SendEmail.visible(true);
eventRule_SendEmailAddress.visible(true);
// BEGIN
//eventRule_SendEmailAddress.text(userInfo.Email);
eventRule_SendEmailAddress.text(
SysUserInfo::find(EventRule.UserId).Email);
// END
}
else
{
alertMeBy.visible(true);
eventRule_ShowPopUp.visible(true);
eventRule_SendEmail.visible(true);
eventRule_SendEmailAddress.visible(true);
// BEGIN
//eventRule_SendEmailAddress.text(userInfo.Email);
eventRule_SendEmailAddress.text(
SysUserInfo::find(EventRule.UserId).Email);
// END
}

if (eventRule.UserId == curuserid())
eventInboxSingleton.enabled(true);
...


Continue reading......

by Patrik Luca 0 comments

23 January 2013

Find method on Temporary tables

Problem: find method not returning rows on a temporary table

Temporary table variables are always newly created, so a static find table method should be written differently compared to regular tables.

Solution

To make your find method work, you need to pass through the reference to the temporary table.

public static TmpAvgCubicMeterPrices find(
ProjId _projId,
InventDimCombinationName _inventDimCombinationName,
TmpAvgCubicMeterPrices _tmpAvgCubicMeterPrices,
boolean _forUpdate = false)
{
TmpAvgCubicMeterPrices tmpAvgCubicMeterPrices;
;

tmpAvgCubicMeterPrices.setTmpData(
_tmpAvgCubicMeterPrices);

tmpAvgCubicMeterPrices.selectForUpdate(_forUpdate);

select firstonly tmpAvgCubicMeterPrices
where tmpAvgCubicMeterPrices.ProjId
== _projId
&& tmpAvgCubicMeterPrices.InventDimCombinationName
== _inventDimCombinationName;


return tmpAvgCubicMeterPrices;
}


Continue reading......

by Patrik Luca 0 comments

11 October 2012

Unwanted changecompany due to refresh SysOperationProgress class

Problem: unexpected changecompany

I was faced with a problem in Dynamics AX 2012, where sometimes an unexpected changecompany happened in a process. Sometimes it occurred, sometimes it didn’t, making it difficult to simulate it.

Solution

The cause of the problem was the SysOperationProgress class. This class can be used to inform the user about status, operation and progress of the system. It was initiated before my changecompany call and closed after it. When the progress bar created by the SysOperationProgress class was refreshed during code execution within my changecompany class, a call is done by X++ to the Docu class. This triggers also a changecompany due my original legal entity. Hence some of my code within my changecompany call was executed in the company to which I did the change, some was done in the company I originated from. And this not all of the time, as it only happened if a refresh happened of my progress bar within the changecompany call. I removed the SysOperationProgress and my problem was solved.


Continue reading......

by Patrik Luca 0 comments

10 October 2012

Create batch job through X++ code

Business requirement

Some flow should execute some code in batch, so you need to add a batch job for the corresponding RunBaseBatch class.

Solution


public static void scheduleBatch()
{
BatchHeader batchHeader;
BatchInfo localBatchInfo;
YourRunBaseBatchClass yourRunBaseBatchClass;
SysRecurrenceData sysRecurrenceData =
SysRecurrence::defaultRecurrence();
;

yourRunBaseBatchClass =
YourRunBaseBatchClass::construct();

// retry 3 times
sysRecurrenceData =
SysRecurrence::setRecurrenceEndAfter(
sysRecurrenceData, 3);
// retry after 1 minute
sysRecurrenceData =
SysRecurrence::setRecurrenceUnit(sysRecurrenceData,
SysRecurrenceUnit::Minute, 1);

localBatchInfo = yourRunBaseBatchClass.batchinfo();
localBatchInfo.parmGroupId("YourBatchGroupId");
batchHeader = batchHeader::construct();
batchHeader.addTask(yourRunBaseBatchClass);
batchHeader.parmRecurrenceData(sysRecurrenceData);
batchHeader.save();
}


Continue reading......

by Patrik Luca 4 comments

06 September 2012

Change dynamically the sorting or grouping in a Report

Business requirement

My user wanted to be able to run a report for which the data could be dynamically grouped and sorted depending on some choice the user made upon starting up the report. According to the choice made, some other Sections should appear in between the grouped report data blocks.

Solution

Create a new BaseEnum, let’s call it ProjCust, with the different sorting and/or grouping possibilities, for example one to group by ProjId and one to group by CustAccount.

Create the report Class.

Define in the classDeclaration a DialogField and variable to handle the different sorting/grouping possibilities for the report.

public class TutorialGroupReport_GroupReport 
extends RunBaseReport
{
    DialogField             dialogReportBy;

    ADUProjCustDlvDate      reportBy;    
#localmacro.CurrentList

        reportBy

    #endmacro
}

In the dialog method, the possibilities to sort/group the report data is shown.


public Object dialog()

{

    DialogRunbase dialog = super();

    ;

    dialog.addGroup("@SYS1046");


    dialogReportBy  =
dialog.addFieldValue(TypeId(ProjCust),
reportBy,
"@SYS55014");


    return dialog;

}

 

In the getFromDialog method, store the sorting/grouping option chosen by the end user


public boolean getFromDialog()  
{

    ;

    reportBy    = dialogReportBy.value();

     return super ();
}

Create a method to return the option chosen by the end user.



ProjCust reportBy()  
{
    return reportBy;
}

 

Create an updateQuery method, which will adapt dynamically the report Query based on the option chosen by the end user



public Query updateQuery()  
{

    Query                   query;
    QueryBuildDataSource    queryBuildDataSource;

    QueryBuildRange         queryBuildRange;
    ;

    query = queryRun.query();

    queryBuildDataSource =
query.dataSourceTable(tableNum(ProjTable));

     switch (this.reportBy())
    {

        case ProjCust::ProjId:
            queryBuildDataSource.addSortField(
fieldNum(ProjTable,ProjId));

            break;
        case ProjCust::CustAccount:

            queryBuildDataSource.addSortField(
fieldNum(ProjTable,CustAccount));
            queryBuildDataSource.addSortField(
fieldNum(ProjTable,ProjId));

            break;
        default:    // In default, error.

            throw error(strFmt("@SYS27147",
this.toString()));
    }

    return query;
}

Call the updateQuery method in the run method.



void run()  
{

    ;

    this.updateQuery();

     super();
}

Add the other appropriate methods to the class, such as a lastValueElementName, pack, unpack, description and main method.



Create the Report and the Design of it.



Add your report Class and the report DataSource to be grouped/sorted dynamically as variable the classDeclaration

public class ReportRun extends ObjectRun  
{

    TutorialGroupReport_GroupReport tutorial_GroupReport;
    ProjTable                       projTable;

}

Assign the caller to the report Class variable in the init method.

public void init()   
{

    super();

     tutorial_GroupReport = element.args().caller();

}


In the fetch method you can change the sorting/grouping dynamically based on the choice of the end user and if necessary add additional design stuff.

public boolean fetch() 

{
    QueryRun        queryRunProjTable;

    ProjId          parentProjId;
    CustAccount     custAccount;

    ;

    queryRunProjTable = new QueryRun(
tutorial_GroupReport.updateQuery());

    this.queryRun(queryRunProjTable);

    while (queryRunProjTable.next())

    {
        projTable = queryRunProjTable.get(
tableNum(ProjTable));


        switch (tutorial_GroupReport.reportBy())
        {

            case ProjCust::ProjId:
                if (projTable.ParentId != parentProjId)

                    this.execute(1);
                    parentProjId = projTable.ParentId;

                break;
            case ProjCust::CustAccount:

                if (projTable.CustAccount != custAccount)
                    this.execute(2);

                    custAccount = projTable.CustAccount;
                break;

            default:    // In default, error.
                throw error(strFmt("@SYS27147",
this.toString()));
        }


        this.send(projTable);
    }

    return true;
}


Continue reading......

by Patrik Luca 0 comments

28 August 2012

Enable trade agreement evaluation on new SalesLine fields

Business requirement: show overwrite prices and discounts dialog for new SalesLine field

If you add a new field to the SalesLine or SalesQuotationLine table, and this field is important for trade agreement evaluations, you should add some code for this field, to enable the Trade Agreement Evaluation functionality. Else, the dialog asking to Overwrite Prices And Discounts won’t appear upon changing this new field.

Solution

Add the new field to the Map PriceDiscResultFields and configure the necessary Mappings with the SalesLine and or SalesQuotationLine table.

In method isTriggerFieldChanged from Map PriceDiscResultFields, add following code for your new field:


boolean lineFieldChanged()
{
    return _priceDiscResultFields.SalesPurchQty        
!= priceDiscResultFieldsOrig.SalesPurchQty
|| _priceDiscResultFields.SalesPurchUnit     
!= priceDiscResultFieldsOrig.SalesPurchUnit
|| _priceDiscResultFields.CurrencyCode       
!= priceDiscResultFieldsOrig.CurrencyCode

          || _priceDiscResultFields.RecieptDeliveryDate
!= priceDiscResultFieldsOrig.RecieptDeliveryDate
          || _priceDiscResultFields.Price
!= priceDiscResultFieldsOrig.Price
          // BEGIN
|| _priceDiscResultFields.YourNewField
!= priceDiscResultFieldsOrig.YourNewField;
// END
}


In Class SalesLineType, method validateField, add following code:



// BEGIN

case fieldNum(SalesLine, YourNewField):

    ok = salesLine.runPriceDiscPolicyDialog();

    break;

// END


Continue reading......

by Patrik Luca 0 comments

Patrik Luca, Ieper, BELGIUM
Feel free to use or spread all of the content on my blog. In return, linking back to my blog would be greatly appreciated. All my posts and articles are provided "AS IS" with no warranties.

Subscribe feeds via e-mail
Subscribe in your preferred RSS reader

Subscribe feeds rss Most Read Entries

Categories

Recommended Books


Subscribe feeds rss Recent Comments

This Blog is part of the U Comment I Follow movement in blogosphere. Means the comment field of this blog is made DOFOLLOW. Spam wont be tolerated.

Blog Archive

My Blog List

Followers

Links