Unretrieve field InventDimId on InventOnHanItem Form

Capture

Add code :
qbsSum.addGroupByField(fieldNum(InventSum,InventDimId));

in the “modifyQuery” method on the “InventDimCtrl_Frm_OnHand” class

Example code

query.clearGroupBy();
qbsSum.addGroupByField(fieldNum(InventSum,ItemId));
qbsSum.addGroupByField(fieldNum(InventSum,InventDimId));

Result:
Capture

Get tax amount through x++

static void TIDgetTax(Args _args)
{
    TaxAmount           tax;
    CustInvoiceTrans    CustInvoiceTrans;
    ;

    CustInvoiceTrans =  CustInvoiceTrans::findRecId(5637155209);
    tax = Tax::calcTaxAmount(CustInvoiceTrans.TaxGroup, CustInvoiceTrans.TaxItemGroup, CustInvoiceTrans.InvoiceDate,
                            CustInvoiceTrans.CurrencyCode, CustInvoiceTrans.LineAmount, TaxModuleType::FreeTxtInvoice);

    info(strfmt('%1', tax));
}

Running Batch Job from X++ example code

static void TID_ExecuteBatchJobDistribution(Args _args)
{
    BatchHeader header;
    SysRecurrenceData sysRecurrenceData;
    Batch batch;
    BatchJob batchJob;
    RetailConnScheduleRunner _RetailConnScheduleRunner; // Class extends RunBaseBatch
    BatchInfo processBatchInfo;
    BatchRetries noOfRetriesOnFailure = 4;
    ;

    // Setup the RunBaseBatch Job
    header = BatchHeader::construct();
    _RetailConnScheduleRunner = new RetailConnScheduleRunner();
    processBatchInfo = _RetailConnScheduleRunner.batchInfo();
    processBatchInfo.parmRetriesOnFailure(noOfRetriesOnFailure);
    processBatchInfo.parmCaption(_RetailConnSchedule.Name); // Description Batch Job
    processBatchInfo.parmGroupId('RTL'); // Batch Gorup
    processBatchInfo.parmBatchExecute(NoYes::Yes);
    header.addTask(_RetailConnScheduleRunner);

    // Set the recurrence data
    sysRecurrenceData = SysRecurrence::defaultRecurrence();
    SysRecurrence::setRecurrenceStartDateTime(sysRecurrenceData, DateTimeUtil::addSeconds(DateTimeUtil::utcNow(), 20)); // Set range of recurrence
    SysRecurrence::setRecurrenceNoEnd(sysRecurrenceData);
    SysRecurrence::setRecurrenceUnit(sysRecurrenceData, SysRecurrenceUnit::Minute); // Set reccurence pattern
    header.parmRecurrenceData(sysRecurrenceData);
    // Set the batch alert configurations
    header.parmAlerts(NoYes::No, NoYes::Yes, NoYes::No, NoYes::Yes, NoYes::Yes);
    header.save();

    // Update the frequency to run the job to every two minutes
    ttsbegin;
    select forupdate batchJob
    join batch
    where batchJob.RecId == batch.BatchJobId
    && batch.ClassNumber == classnum(RetailConnScheduleRunner);

    sysRecurrenceData = batchJob.RecurrenceData;
    sysRecurrenceData = conpoke(sysRecurrenceData, 8, [10]);
    batchJob.RecurrenceData = sysRecurrenceData;
    batchJob.update();
    ttscommit;
}

marking inventTrans example code

public static void FNDMarkInventTrans(InventTransId _inventTransId,InventTransId _refInventTransId,InventQty _qtyTomark)
{
    InventTrans issueInventTrans;
    TmpInventTransMark tmpInventTransMask;
    Map mapMarkNow;
    container con;
    real qty;
    Map mapTmp;
    MapEnumerator mapEnumerator;

    InventTransOriginId issueInventTransOriginId =
        InventTransOrigin::findByInventTransId(_inventTransId).RecId;

    InventTransOriginId receiptInventTransOriginId =
        InventTransOrigin::findByInventTransId(_refInventTransId).RecId;

    InventQty qtyToMark = _qtyTomark;

    ttsBegin;

    issueInventTrans = InventTrans::findByInventTransOrigin(
        issueInventTransOriginId);

    [con, qty] = TmpInventTransMark::packTmpMark(
        InventTransOrigin::find(issueInventTransOriginId),
        issueInventTrans.inventDim(),
        issueInventTrans.Qty);

    mapTmp = Map::create(con);
    mapEnumerator = mapTmp.getEnumerator();
    while (mapEnumerator.moveNext())
    {
        tmpInventTransMask = mapEnumerator.currentValue();

        if (tmpInventTransMask.InventTransOrigin == receiptInventTransOriginId)
        {
            tmpInventTransMask.QtyMarkNow = qtyToMark;
            tmpInventTransMask.QtyRemain -= tmpInventTransMask.QtyMarkNow;
            mapMarkNow = new Map(Types::Int64, Types::Record);
            mapMarkNow.insert(tmpInventTransMask.RecId, tmpInventTransMask);

            TmpInventTransMark::updateTmpMark(
                issueInventTransOriginId,
                issueInventTrans.inventDim(),
                -qtyToMark,
                mapMarkNow.pack());
        }
    }

    ttsCommit;
}

reference code :
https://community.dynamics.com/ax/b/dynamicsaxnotesonthecuffs/archive/2013/01/08/marking-from-code-part-2

get Available budget example code

source code from form : BudgetControlStatistics
Capture

example code :

  static void TIDF_getBudgetAvailable(Args _args)
{
    
    //class and table
    BudgetControlStatisticsManager budgetControlStatsManager = new BudgetControlStatisticsManager();
    
    //table
    BudgetTmpControlStatistics  currentBudgetTmpControlStatistics;
    BudgetCycle                 budgetCycle;
    BudgetCycleTimeSpan         budgetCycleTimeSpan;
    FiscalCalendar              fiscalCalendar;
    DimensionAttributeValueCombination dimensionAttributeValueCombination;
    DimensionHierarchy          dimensionHierarchy;
    
    //variable
    DimensionValue  dim1;
    container       conDimValue;
    MainAccountNum  mainAccountNum;
    RecId           ledgerDimension;
    
    //financial dimension
    mainAccountNum = "6100-1001";
    dim1           = "5102";
    
    select firstonly dimensionAttributeValueCombination 
    where 
        dimensionAttributeValueCombination.DisplayValue == strFmt("%1-%2",mainAccountNum,dim1)
    &&  dimensionAttributeValueCombination.LedgerDimensionType == LedgerDimensionType::BudgetControl;
    
    //budget cycle
    fiscalCalendar   = fiscalCalendar::findByCalendarId("2016");
    BudgetCycleTimeSpan = budgetCycleTimeSpan::findByNameAndCalendar("SEM",fiscalCalendar.RecId);
    BudgetCycle =  budgetCycle::findBudgetCycleByDate(BudgetCycleTimeSpan.RecId,today());
    
    currentBudgetTmpControlStatistics = budgetControlStatsManager.fillBudgetTmpControlStatistics(Ledger::current(),
                                                                                                'ALL',
                                                                                                BudgetControlStatisticsPeriodOption::FiscalPeriod,
                                                                                                BudgetBalanceType::Accumulated,
                                                                                                BudgetCycle.RecId,
                                                                                                dimensionAttributeValueCombination.RecId,
                                                                                                0,
                                                                                                0,
                                                                                                true,
                                                                                                NoYes::No,
                                                                                                true);
    
   while select  currentBudgetTmpControlStatistics
   {
        info(strFmt("%1 -- %2 ",currentBudgetTmpControlStatistics.PeriodStartDate,currentBudgetTmpControlStatistics.TotalFundsAvailableAmountMST));
   }

}

result :
Capture

Auto Approve Workflow by Code x++

Example code :

static void TIDF_autoApproveWFOvertime(Args _args)
{
    WorkflowWorkItemTable WorkflowWorkItemTable;

    while select WorkflowWorkItemTable
    where
        WorkflowWorkItemTable.UserId == '32501112'
    &&  workflowWorkItemTable.Type == WorkflowWorkItemType::WorkItem
    &&  workflowWorkItemTable.Status == WorkflowWorkItemStatus::Pending
    &&  WorkflowWorkItemTable.RefTableId == tableNum(HrsOvertime)
    {
        WorkflowWorkItemActionManager::dispatchWorkItemAction(
                                    WorkflowWorkItemTable,
                                    "Auto Approve by ADMIN", // comment
                                    '32501112', // << user ID
                                    WorkflowWorkItemActionType::Complete,
                                    "HRSOvertimeApprove", // << menu item action approval workflow
                                    false); //is not web Menu Item
    }

}

Capture

Resume Workflow from x++ example code

example code :

static void TIDF_resumeWFOverTime(Args _args)
{
    WorkflowTrackingStatusTable WorkflowTrackingStatusTable;
    HrsOvertime                 hrsOverTime;
    
    
    while select WorkflowTrackingStatusTable 
    where 
        WorkflowTrackingStatusTable.TrackingStatus == WorkflowTrackingStatus::Faulted 
    && WorkflowTrackingStatusTable.WorkflowType == WorkflowTrackingStatusWorkflowType::Workflow
    && WorkflowTrackingStatusTable.ContextTableId == tableNum(HrsOvertime)
    {
        //consistency check valid data
        select firstOnly hrsOverTime where hrsOverTime.RecId == WorkflowTrackingStatusTable.ContextRecId;
        if(hrsOverTime)
        {
            Workflow::resumeWorkflow(WorkflowTrackingStatusTable.CorrelationId);      
        }
    }
}

source : https://community.dynamics.com/ax/f/33/t/126119

get USER ID and Security Role from HcmWorker

Example Code :

display Notes TIDgetUserIdAndRoles()
{
    DirPerson               DirPerson;
    DirPersonUser           DirPersonUser;
    SecurityUserRole        SecurityUserRole;
    SecurityRole            SecurityRole;
    Notes                   returnNotes;
    str value;
    ;


    DirPerson       = DirPerson::find(this.Person);
    DirPersonUser   = DirPersonUser::findWorker(this.RecId);
    returnNotes      = strFmt("User ID : %1 \n\n ",DirPersonUser.User);
    returnNotes      = strFmt("%1Security Roles : \n",returnNotes);
    
    while select * from SecurityUserRole 
        where SecurityUserRole.User == DirPersonUser.User
    join SecurityRole
        where SecurityRole.RecId == SecurityUserRole.SecurityRole
    {
        if(subStr(SecurityRole.Name,1,1) == '@')
        {
            value = SysLabel::labelId2String2(SecurityRole.Name, companyinfo::languageId());
            returnNotes = strFmt("%1 %2\n",returnNotes,value);
        }
        else
        {
            returnNotes = strFmt("%1 %2\n",returnNotes, SecurityRole.Name);
        }
    }
    
    return returnNotes;
}

check user workflow hierarchy by code x++

i found a nice code for checking user workflow hierarchy approver and solved the related error.

static void navax_workflowHierarchyTester(Args _args)
{
    WorkflowTypeName                    workflowTemplateName = 'TIDEmploymentLeave';
    //TrvExpTrans                         trvExpTrans;
    //TrvExpNumber                        trvExpNum = '000015'; //Expense id

    HcmEmploymentLeave                  hcmEmploymentLeave;
    str                                 nodeId = '23511014'; //Starting worker id
    WorkflowHierarchyLevel              level = 0;
    WorkflowContext                     workflowContext;
    SysWorkflowTable                    workflowTable;
    WorkflowLimitHierarchyProvider      workflowLimitHierarchyProvider;
    WorkflowHierarchyProviderNode       workflowHierarchyProviderNode;
    HRPWorkerLimit                      workerLimit = new HRPWorkerLimit();
    HcmWorker                           hcmWorker;
    DirPersonUser                       dirPersonUser;
    RefRecId                            hcmPositionRecId;
    HcmPosition                         hcmPosition;
    container                           spendingCon, approvalCon;
    UserId                              userId;

    select firstOnly workflowTable
        where workflowTable.TemplateName == workflowTemplateName;

    select firstOnly hcmEmploymentLeave
        where hcmEmploymentLeave.HRSLeaveReqId ==  &quot;LV-00635&quot; ;

    workflowContext = WorkflowContext::newWorkflowContext(
        curext(),
        tableNum(hcmEmploymentLeave),
        hcmEmploymentLeave.RecId,
        workflowTable.WorkflowCorrelationId);

    workflowLimitHierarchyProvider = new WorkflowLimitHierarchyProvider();

    //Level 1
    while (nodeId &amp;&amp; level &lt; 20) //20 is just a fall back. In case it goes into an endless loop.
    {
        workflowHierarchyProviderNode   = workflowLimitHierarchyProvider.getNextNode(nodeId, level, workflowContext);
        nodeId                          = workflowHierarchyProviderNode.getnodeId();
        hcmWorker                       = HcmWorker::findByPersonnelNumber(nodeId);
        userId                          = DirPersonUser::findParty(hcmWorker.Person).User;
        hcmPositionRecId                = HcmWorker::getPrimaryPosition(hcmWorker.RecId);
        hcmPosition                     = HcmPosition::find(hcmPositionRecId);

        spendingCon = workerLimit.getWorkerSigningLimit(
            hcmWorker.RecId,
            SourceDocumentRelationType::ExpenseReport,
            HRPLimitType::Spending,
            hcmPosition.PositionId);

        approvalCon = workerLimit.getWorkerSigningLimit(
            hcmWorker.RecId,
            SourceDocumentRelationType::ExpenseReport,
            HRPLimitType::Approval,
            hcmPosition.PositionId);

        info(strFmt(&quot;UserId: %1 | WorkerId: %2 | PositionId: %3 | ReportsToPosition: %4 | SpendingLimit: %5 | ApprovalLimit: %6&quot;,
            userId,
            hcmWorker.PersonnelNumber,
            hcmPosition.PositionId,
            hcmPosition.reportsToPosition(),
            con2Str(spendingCon),
            con2Str(approvalCon)
            ));

        level++;
    }
}

source :
https://community.dynamics.com/ax/b/dynamicsnavax/archive/2015/06/08/workflow-hierarchy-assignment-common-errors-explained-and-tester-job-ax-2012

Job upload fixed assets master data with value models example code

Job

static void TIDF_uploadFAwithValueModels(Args _args)
{
    AssetId             assetId;
    AssetGroupId        assetGroupId;
    AssetName           assetName;
    AssetLocationId     assetLocationId;
    AssetServiceLife    assetServiceLife;
    AssetLifeTimeRest   assetLifeTimeRest;
    AssetPostingProfile assetPostingProfile;
    AssetBookId         assetBookId;
    TransDate           depreciationStartDate,LastDepreciationDate,AcquisitionDate;
    RecId               recIdDefaultDimension;
    AssetLongDescription AssetLongDescription;

    AxAssetTable        axAssetTable;

    //table
    AssetTable          assetTable;
    AssetGroup          assetGroup;
    AssetLocation       assetLocation;
    AssetBook           assetBook;
    AssetLedger         assetLedger;

    container   financialDimensionFromExcel;
    container   conDimensionName;

    SysExcelApplication                         application = SysExcelApplication::construct();
    SysExcelWorkbooks                           workbooks   = application.workbooks();
    SysExcelWorkbook                            workbook;
    SysExcelWorksheets                          workSheets;
    SysExcelWorksheet                           workSheet;
    SysExcelCells                               cells;
    SysExcelCell                                cell;
    int                                         row;
    str                                         filename;
    ;

    startLengthyOperation();
    //variable yang diisi manual
    //C:\#TECTURA\Master Data
    filename              = "C:\\#TECTURA\\Master Data\\FA Master_Budi00.xlsx";
    assetPostingProfile   = "FA POSTING";
    depreciationStartDate = today();
    LastDepreciationDate  = today();
    AcquisitionDate       = today();

    try
    {
        if (workbooks.open(filename, false /*Update links*/, true /*Read only*/))
        {
            workbook   = workbooks.item(1);
            workSheets = workbook.worksheets();
            workSheet  = workSheets.itemFromNum(1); //worksheet keberapa dari excel di mulai dari angka 1
            cells      = workSheet.cells();
            conDimensionName = TIDgetDimensionName();

            row = 5;

            ttsBegin;
            while (cells.item(row,2).value().bStr() != "")
            {
                //financial dimension
                financialDimensionFromExcel = conNull();
                //dimension value 1
                financialDimensionFromExcel += cells.item(row,7).value().bStr();
                //dimension value 2
                financialDimensionFromExcel += cells.item(row,8).value().bStr();
                //dimension value 3
                financialDimensionFromExcel += cells.item(row,9).value().bStr();
                //dimension value 4
                financialDimensionFromExcel += cells.item(row,10).value().bStr();
                //dimension value 5
                financialDimensionFromExcel += cells.item(row,11).value().bStr();
                //dimension value 6
                financialDimensionFromExcel += cells.item(row,12).value().bStr();
                //generateDefaultDimension
                recIdDefaultDimension       = TIDcreateDefaultDimension(conDimensionName,financialDimensionFromExcel);

                //variable
                assetId           = TIDComVariant2STR(cells.item(row,2).value());
                assetGroupId      = TIDComVariant2STR(cells.item(row,1).value());
                assetLocationId   = TIDComVariant2STR(cells.item(row,6).value());
                assetName         = TIDComVariant2STR(cells.item(row,3).value());
                assetServiceLife  = str2num(TIDComVariant2STR(cells.item(row,4).value()));
                assetLifeTimeRest = str2num(TIDComVariant2STR(cells.item(row,5).value()));
                assetBookId          = TIDComVariant2STR(cells.item(row,13).value());
                AssetLongDescription = TIDComVariant2STR(cells.item(row,14).value());
                //table
                assetTable      = assetTable::find(assetId);
                assetGroup      = AssetGroup::find(assetGroupId);
                assetLocation   = AssetLocation::find(assetLocationId);

                //validation
                if(!assetGroup || !assetLocation)
                {
                    throw error(strFmt("Row : %1 ,Asset group or asset location not existed, please check again",row));
                }
                //create asset Table
                if(!assetTable)
                {
                    axAssetTable    = new AxAssetTable();
                    axAssetTable.parmAssetId(assetId);
                    axAssetTable.parmAssetGroup(assetGroupId);
                    axAssetTable.parmName(assetName);
                    axAssetTable.parmLocation(assetLocationId);
                    axAssetTable.parmLocationMemo(AssetLongDescription);
                    axAssetTable.save();
                }

                //create assetBook
                assetBook = assetBook::find(assetId,assetBookId);
                if(!assetBook)
                {
                    assetBook.clear();
                    assetBook.initValue();
                    assetBook.AssetId               = assetId;
                    assetBook.BookId                = assetBookId;
                    assetBook.PostingProfile        = assetPostingProfile;
                    assetBook.ServiceLife           = assetServiceLife;
                    assetBook.LifeTime              = assetServiceLife*12;
                    assetBook.LifeTimeRest          = assetLifeTimeRest;
                    assetBook.DepreciationStartDate = depreciationStartDate;
                    assetBook.LastDepreciationDate  = LastDepreciationDate;
                    assetBook.AcquisitionDate       = AcquisitionDate;
                    assetBook.DefaultDimension      = recIdDefaultDimension;
                    assetBook.insert();
                }
                else
                {
                    assetBook.selectForUpdate(true);
                    assetBook.ServiceLife           = assetServiceLife;
                    assetBook.LifeTime              = assetServiceLife*12;
                    assetBook.LifeTimeRest          = assetLifeTimeRest;
                    assetBook.DepreciationStartDate = depreciationStartDate;
                    assetBook.LastDepreciationDate  = LastDepreciationDate;
                    assetBook.AcquisitionDate       = AcquisitionDate;
                    assetBook.DefaultDimension      = recIdDefaultDimension;
                    assetBook.update();
                }


                print strFmt('FA Group : %1 FAID : %2 Name : %3',assetGroupId,assetId,assetName);
                row++;
            }
            ttsCommit;
            info("Success");
            application.quit();
        }
    }
    catch(Exception::Error)
    {
        info("Fixed Asset upload Error");
        application.quit();
    }
}

TIDGetDimensionName

public static container TIDgetDimensionName()
{
    DimensionAttribute              dimAttr;
    DimensionAttributeSetItem       dimAttrSetItem;
    DimensionEnumeration            dimensionSetId;
    DimensionAttributeValue         dimAttributeValue;
    container                       DimensionName;

    dimensionSetId      = DimensionCache::getDimensionAttributeSetForLedger();

    while select dimAttr order by Name
                where dimAttr.Type != DimensionAttributeType::MainAccount
            join RecId from dimAttrSetItem
                where dimAttrSetItem.DimensionAttribute     == dimAttr.RecId &&
                      dimAttrSetItem.DimensionAttributeSet  == dimensionSetId
            {
                dimensionName += dimAttr.Name;

            }

    return DimensionName;
}

TIDCreateDefaultDimension

static DimensionDefault TIDcreateDefaultDimension(container _attr, container _value, boolean _createIfNotFound = true)
{
    DimensionAttributeValueSetStorage   valueSetStorage = new DimensionAttributeValueSetStorage();
    DimensionDefault                    result;
    int                                 i;
    DimensionAttribute                  dimensionAttribute;
    DimensionAttributeValue             dimensionAttributeValue;
    //_attr is dimension name in table DimensionAttribute
    container               conAttr =   _attr;
    container               conValue = _value;
    str                     dimValue;

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

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

        dimValue = conPeek(conValue,i);

        if (dimValue != "")
        {
            // _createIfNotFound is "true". A dimensionAttributeValue record will be created if not found.
            dimensionAttributeValue = dimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,dimValue,false,_createIfNotFound);

            // Add the dimensionAttibuteValue to the default dimension
            valueSetStorage.addItem(dimensionAttributeValue);
        }
    }
    result = valueSetStorage.save();
    return result;
}

TIDComVariant2STR

public static str TIDComVariant2STR(COMVariant _variant)
{
    str valueStr;
    ;

    switch(_variant.variantType())
    {
        case COMVariantType::VT_EMPTY   :
            valueStr = '';
            break;

        case COMVariantType::VT_BSTR    :

            valueStr = _variant.bStr();
            break;

        case COMVariantType::VT_R4      :
        case COMVariantType::VT_R8      :

            if(_variant.double())
            {
                valueStr = strFmt("@SYS311964",
                                    num2Str0(_variant.double(), 0),
                                    num2str(_variant.double(),
                                    0,
                                    numOfDec(_variant.double()),
                                    1,
                                    0));
            }
            break;

        default                         :
            throw error(strfmt("@SYS26908",
                                _variant.variantType()));
    }

    return valueStr;
}

Filter DataSets Field Lookup Enterprise Portal example code

on AOT datasets fields method, add this code below :

void dataSetLookup(SysDataSetLookup sysDataSetLookup)
{
    List list = new List(Types::String);
    Query query = new Query();

    // Add the table to the query.
    query.addDataSource(tableNum(HcmLeaveType));

    //filter query
    query.dataSourceTable(tableNum(HcmLeaveType)).addRange(fieldNum(HcmLeaveType,ValidToCredit)).value(SysQuery::value(NoYes::Yes));

    /* uncomment if the relation is not based on reference recid
    // Specify the fields to use for the lookup.
    list.addEnd(fieldStr(HcmLeaveType,LeaveTypeId));
    list.addEnd(fieldStr(HcmLeaveType,Description));

    // Supply the set of lookup fields.
    sysDataSetLookup.parmLookupFields(list);

    // Specify the field that is returned from the lookup.
    sysDataSetLookup.parmSelectField(fieldStr(HcmLeaveType,LeaveTypeId));
    sysDataSetLookup.parmHideSelectField(true);
    */ 

    // Pass the query to the SysDataSetLookup so that the query is used.
    sysDataSetLookup.parmQuery(query);
}

preview after lookup filtered by code :
Capture

reference on MSDN :
https://msdn.microsoft.com/en-us/library/hh830903.aspx

Useful powershell command for export and install AXModel

Export axmodel layer example :
Export-AXModel -Model CUS Model -config MicrosoftDynamicsAXUAT -file CUS.axmodel
Capture2

Import axmodel with replace and create parent example :
Install-AXModel -File CUS.axmodel -Conflict Overwrite -Config MicrosoftDynamicsAXUAT -createparents
Capture

reference link :
http://axbloggerblog.blogspot.co.id/p/powershell-commands.html

do full compile, full sync db, full CIL and incremental. Re-deploy website EP if you are customize the EP

convert null to 0 type BIGINT (INT64 on AX) when outer join on view using SysComputedColumn

public static server str DefaultDimension()
{

    str field = SysComputedColumn::returnField(tableStr(HRSJobPositionDefaultDimension),
                    identifierStr(HcmPositionDefaultDimension),
                    fieldStr(HcmPositionDefaultDimension, DefaultDimension));
    
    return SysComputedColumn::if(
        SysComputedColumn::isNullExpression(field),
        SysComputedColumn::cast("0",'BIGINT'),  
        SysComputedColumn::cast(field,'BIGINT'));
}

add new default dimension (financial dimension) on new table and form example tutorial

This example tutorial will guide you to add new default dim on table and forms.

1. Add new field with type Int64 and set the properties.
Capture

2. Add relation on table relation and set the properties.
Capture

3. on class declaration form , add code below :

public class FormRun extends ObjectRun
{
    DimensionDefaultingController   dimensionDefaultingController;
}

4. add tab page Financial Dimension on form design , and set properties like img below
Capture

5. on TabFinancialDimensions , override method pageActivated

public void pageActivated()
{
    dimensionDefaultingController.pageActivated();

    super();
}

6. on init form, like code below :

public void init()
{
    super();
    dimensionDefaultingController = DimensionDefaultingController::constructInTabWithValues(true, true, true, 0, this, TabFinancialDimensions, "@SYS138487", curext());
    dimensionDefaultingController.parmAttributeValueSetDataSource(HRSJobPowerPlan_ds, fieldStr(HRSJobPowerPlan, DefaultDimension));
}

7. finnaly, on datasource form method override method :
on active()

public int active()
{
    int ret;

    ret = super();
    dimensionDefaultingController.activated();

    return ret;
}

on write()

public void write()
{
    dimensionDefaultingController.writing();
    super();
}

on delete()

public void delete()
{
    dimensionDefaultingController.deleted();
    super();
}

8. preview example form:
Capture

add group by and ranges to Queries Forms example code

on form class declaration

public class FormRun extends ObjectRun
{
    QueryBuildRange             indentTransDateRange;
    QueryBuildRange             invoiceDateRange;

    QueryBuildRange             customerRange;
    QueryBuildRange             storeRange;
}

on init form method

public void init()
{
    super();

    indentTransDateRange = TIDIndentOrderUninvoiceTrans_ds.query().dataSourceTable(tablenum(TIDIndentOrderUninvoiceTrans))
    .addRange(fieldnum(TIDIndentOrderUninvoiceTrans, PaymentTransDate));

    invoiceDateRange = TIDIndentOrderUninvoiceTrans_ds.query().dataSourceTable(tablenum(TIDIndentOrderUninvoiceTrans))
    .addRange(fieldnum(TIDIndentOrderUninvoiceTrans, InvoicePostingDate));

    customerRange = TIDIndentOrderUninvoiceTrans_ds.query().dataSourceTable(tablenum(TIDIndentOrderUninvoiceTrans))
    .addRange(fieldnum(TIDIndentOrderUninvoiceTrans, CustAccount));

    storeRange = TIDIndentOrderUninvoiceTrans_ds.query().dataSourceTable(tableNum(TIDIndentOrderUninvoiceTrans))
    .addRange(fieldNum(TIDIndentOrderUninvoiceTrans, Store));

    TransactionDate.dateValue(systemdateGet());
}

on execute Query datasource form

public void executeQuery()
{
    this.Query().clearGroupBy();

    indentTransDateRange.value(strFmt('<%1',(TransactionDate.dateValue() + 1)));
    invoiceDateRange.value(strFmt('>%1',TransactionDate.dateValue()));

    customerRange.value(strFmt(customer.text()+'*'));
    storeRange.value(strFmt(StoreId.text()+'*'));

    this.Query().DataSourceNo(1).addGroupByField(fieldNum(TIDIndentOrderUninvoiceTrans,Store));
    this.Query().DataSourceNo(1).addGroupByField(fieldNum(TIDIndentOrderUninvoiceTrans,CustAccount));
    this.Query().DataSourceNo(1).addGroupByField(fieldNum(TIDIndentOrderUninvoiceTrans,SalesId));
    this.Query().DataSourceNo(1).addGroupByField(fieldNum(TIDIndentOrderUninvoiceTrans,GrossAmount));
    this.Query().DataSourceNo(1).addSelectionField(fieldNum(TIDIndentOrderUninvoiceTrans,SumOfamountTendered),SelectionField::Sum);
    this.Query().DataSourceNo(1).addSelectionField(fieldNum(TIDIndentOrderUninvoiceTrans,OutstandingAmount),SelectionField::Sum);

    super();
}

Capture

Formating cells when export to excel example code

private void setInvoiceHeader(SysExcelWorkSheet    xlsWorkSheet,CustInvoiceJour custInvoiceJour)
{
    xlsWorkSheet.cells().item(row,1).value("FK");
    xlsWorkSheet.cells().item(row,2).value(str2num(CustTable::find(custInvoiceJour.InvoiceAccount).TECFakturPajakTypeId));
    xlsWorkSheet.cells().range(strFmt("B%1:B%1",row)).numberFormat("00");
    xlsWorkSheet.cells().item(row,3).value(enum2int(custInvoiceJour.TECIsSubtitute));
    xlsWorkSheet.cells().item(row,4).value(str2num(strFmt("%1", strRem(custInvoiceJour.TECFakturPajakListId, ".-"))));
    xlsWorkSheet.cells().range(strFmt("D%1:D%1",row)).numberFormat("0000000000000");
    xlsWorkSheet.cells().item(row,5).value(mthOfYr(custInvoiceJour.InvoiceDate));
    xlsWorkSheet.cells().item(row,6).value(year(custInvoiceJour.InvoiceDate));
    xlsWorkSheet.cells().item(row,7).value(date2str(custInvoiceJour.InvoiceDate, 213, 1, 4, 1, 4, 4));
    xlsWorkSheet.cells().item(row,8).value(str2num(strFmt("%1", strRem(custInvoiceJour.custTable_InvoiceAccount().TECNPWP, ".-"))));
    xlsWorkSheet.cells().range(strFmt("H%1:H%1",row)).numberFormat("00000000000000");
    xlsWorkSheet.cells().item(row,9).value(CustTable::find(custInvoiceJour.InvoiceAccount).name());
    xlsWorkSheet.cells().item(row,10).value(strRTrim(CustTable::find(custInvoiceJour.InvoiceAccount).postalAddress().Street));
    xlsWorkSheet.cells().item(row,11).value(round(custInvoiceJour.SalesBalance,0));
    xlsWorkSheet.cells().range(strFmt("K%1:K%1",row)).numberFormat("0");
    xlsWorkSheet.cells().item(row,12).value(round(custInvoiceJour.SumTax,0));
    xlsWorkSheet.cells().range(strFmt("L%1:L%1",row)).numberFormat("0");
    xlsWorkSheet.cells().item(row,13).value(0);
    xlsWorkSheet.cells().item(row,14).value("");
    xlsWorkSheet.cells().item(row,15).value(0);
    xlsWorkSheet.cells().item(row,16).value(0);
    xlsWorkSheet.cells().item(row,17).value(0);
    xlsWorkSheet.cells().item(row,18).value(0);
    xlsWorkSheet.cells().item(row,19).value(custInvoiceJour.InvoiceId);
    row++;
    totalCount++;
}

Capture

more example and source :
http://patrikluca.blogspot.cz/2010/04/export-to-excel-with-x-code-sequel.html

ODBC from x++ example code

public client static void processMDBData(str _StrDSN, str _StrTableName, date _DateFrom, date _DateTo)
{
    #AviFiles
    SysOperationProgress    progress = new SysOperationProgress();
    OdbcConnection          C;
    Statement               S;
    LoginProperty           LP = new LoginProperty();
    ResultSet               RS;
    HcmPersonnelNumberId    _EmplID;
    TimeHour24              _Time;
    str                     strquery,strDSN,tableName;
    Date                    _Date;
    int                     Idx;
    HRSTMAttendanceTemp     attDataTemp;

    ;

    try
    {   
        strDSN    = _StrDSN;
        tableName = _StrTableName;

        ttsbegin;
        LP.setDSN(_strDSN);
        LP.setServer("S-AOS1TEST");

        C   = new OdbcConnection(LP);
        S   = C.createStatement();


        strquery    = strFmt("SELECT * FROM %1 where dateLog >= #%2# AND dateLog <= #%3#",tableName,_DateFrom,_DateTo);
        RS  = S.executeQuery(strquery);
        while (RS.next())
        {
            //Progress.incCount();
            _EmplID = Rs.getString(1);
            _Date   = RS.getDate(2);
            _Time   = str2time(RS.getString(3));
            Idx     = str2int(rs.getString(4));
            
            //insert to temp table
            if(_EmplID == '') continue;
            select forupdate attDataTemp
            where attDataTemp.PersonnelNumber == _EmplID && attDataTemp.Time == _Time
                                  && attDataTemp.TransDate == _Date;
            if(!attDataTemp)
            {
                attDataTemp.clear();
                attDataTemp.PersonnelNumber      = _EmplID;
                attDataTemp.Time        = _Time;
                attDataTemp.TransDate   = _Date;
                attDataTemp.Idx         = Idx;
                attDataTemp.insert();
            }
            else
            {
                attDataTemp.Idx         = Idx;
                attDataTemp.ClockId     = '';
                attDataTemp.update();
            }

            Progress.setText(strfmt("Upload Id %1 - %2 %3", _EmplID, _date, time2str(_time, 1, 1)));
        }
        ttsCommit;

   }
   catch
   {
       ttsAbort;
       return;
   }
}

example code on custom class ApprovalResubmitActionMgr

example code :

public static void main(Args _args)
{
    recID                           recID               = _args.record().RecId;
    tableId                         tableId             = _args.record().TableId;
    HcmEmploymentLeave              HcmEmploymentLeave  = _args.record();
    WorkflowWorkItemTable           workItem            = _args.caller().getActiveWorkflowWorkItem();
    str                             menuItemName        = _args.menuItemName();
    WorkflowWorkItemActionDialog    workflowWorkItemActionDialog;
    WorkflowSubmitDialog            workflowSubmitDialog;
     
    Debug::assert(tableId == tablenum(HcmEmploymentLeave));
    Debug::assert(recId != 0);

    // The method has not been called correctly.
    if (tableId != tablenum(HcmEmploymentLeave) ||
        recId == 0)
    {
        throw error(strfmt("@SYS19306", funcname()));
    }

    // The journal has an active workflow.
    if (workItem.RecId > 0)
    {
        try
        {
            // The journal does support workflow approvals.
            workflowWorkItemActionDialog = WorkflowWorkItemActionDialog::construct( workItem,
                                                                                    WorkflowWorkItemActionType::Resubmit,
                                                                                    new MenuFunction(_args.menuItemName(),_args.menuItemType()));
            workflowWorkItemActionDialog.run();
            if (workflowWorkItemActionDialog.parmIsClosedOK())
            {

                workItem    = _args.caller().getActiveWorkflowWorkItem();
                WorkflowWorkItemActionManager::dispatchWorkItemAction(  workItem,
                                                                    workflowWorkItemActionDialog.parmWorkflowComment(),
                                                                    workflowWorkItemActionDialog.parmTargetUser(),
                                                                    WorkflowWorkItemActionType::Resubmit,
                                                                    _args.menuItemName(),
                                                                    false);
              
            }
        }

        catch(Exception::Error)
        {
            throw error(strfmt("Leave %1 can't be submitted", HcmEmploymentLeave.HRSLeaveReqId));
        }
    }
    // Make the form refresh its common workflow UI controls.
    _args.caller().updateWorkflowControls();
}

get Standard Cost Price Item Based on Activation date and InventSiteId

public static Price TIDgetSTDCostItemPrice(ItemId _itemId,TransDate _activationDate,InventSiteId _inventSiteId)
{
    InventDim       InventDimLoc;
    InventItemPrice inventItemPriceLoc;
    
    InventDimLoc.clear();
    InventDimLoc.InventSiteId = _inventSiteId;
    InventDimLoc = InventDim::findOrCreate(InventDimLoc);
    
    inventItemPriceLoc = InventItemPrice::findCurrent(_itemId,CostingVersionPriceType::Cost,InventDimLoc.inventDimId,
                                                      _activationDate,_inventSiteId,InventItemCostingType::Standard);
    
    return inventItemPriceLoc.Price;
}

send email via x++ example code

static boolean sendEmail(str toAddress, str theSubject, str body, str fromAddress)
{
    SysEmailParameters parameters = SysEmailParameters::find();

    System.Net.Mail.SmtpClient            mailClient;
    System.Net.Mail.MailMessage           mailMessage;
    System.Net.Mail.MailAddress           mailFrom;
    System.Net.Mail.MailAddress           mailTo;
    System.Net.Mail.MailAddressCollection mailToCollection;
    System.Net.Mail.MailAddressCollection mailCCCollection;
    System.Net.Mail.AttachmentCollection  mailAttachementCollection;
    System.Net.Mail.Attachment            mailAttachment;
    System.Net.NetworkCredential          mailCredentials;

    System.Exception                      e;
    List            toList;
    ListEnumerator  le;


    SMTPRelayServerName mailServer;
    SMTPPortNumber mailPortNumber;
    SMTPUserName mailUserName;
    SMTPPassword mailPassword;

    InteropPermission interopPermission;
    ;

    try
    {
        interopPermission = new InteropPermission(InteropKind::ComInterop);
        interopPermission.assert();

        if (parameters.SMTPRelayServerName)
        {
            mailServer = parameters.SMTPRelayServerName;
        }
        else
        {
            mailServer = parameters.SMTPServerIPAddress;
        }

        mailPortNumber  = parameters.SMTPPortNumber;
        mailUserName    = parameters.SMTPUserName;
        mailPassword    = SysEmailParameters::password();
        mailCredentials = new System.Net.NetworkCredential(mailUserName,mailPassword);


        mailClient = new System.Net.Mail.SmtpClient(mailServer, mailPortNumber);
        mailFrom = new System.Net.Mail.MailAddress(parameters.SMTPUserName); //fromAddress);

        toList = strSplit(toAddress,';');
        le = toList.getEnumerator();
        le.moveNext();

        mailTo  = new System.Net.Mail.MailAddress(strLTrim(strRTrim(le.current())));
        mailMessage = new System.Net.Mail.MailMessage(mailFrom, mailTo);

        mailToCollection = mailMessage.get_To();
        while(le.moveNext())
        {
            mailToCollection.Add(strLTrim(strRTrim(le.current())));
        }


        mailMessage.set_From(mailFrom);
        mailMessage.set_ReplyTo(mailFrom);
        mailMessage.set_Priority(System.Net.Mail.MailPriority::High);
        mailMessage.set_Subject(theSubject);
        mailMessage.set_IsBodyHtml(true);
        mailMessage.set_Body(body);

        if(parameters.TIDUsingSSLorTSL)
        {
            mailClient.set_EnableSsl(true);
            mailClient.set_UseDefaultCredentials(false);
            mailClient.set_Credentials(mailCredentials);
        }
        else
        {
            mailClient.set_EnableSsl(false);
        }


        mailClient.Send(mailMessage);

        mailMessage.Dispose();

        CodeAccessPermission::revertAssert();

        //info("Email has been send.");
    }
    catch (Exception::CLRError)
    {
        e = ClrInterop::getLastException();
        while (e)
        {
            info(e.get_Message());
            e = e.get_InnerException();
        }
        CodeAccessPermission::revertAssert();
        return false;
    }
}

source : my senior’s code

find Physical Inventory Qty by date

i modified code originated from DAXDUDE ,
i added inventQty = inventSumDateDim.postedQty()-InventSumDateDim.deductedQty()+InventSumDateDim.postedQty() to get physical inventory

static void TIDF_getInventPhysicalbyDate(Args _args)
{
    InventDimParm inventDimParmCrit;
    InventSumDateDim inventSumDateDim;
    InventDim inventDim = InventDim::find('AllBlank');
    InventQty inventQty;
    ;

    // Set the dimensions
    inventDimParmCrit.initFromInventDim(inventDim);
    inventSumDateDim = inventSumDateDim::newParameters(today(), '010410003', inventDim, inventDimParmCrit);
    inventQty =  inventSumDateDim.receivedQty()-InventSumDateDim.deductedQty()+InventSumDateDim.postedQty();

    info(strFmt("%1",inventQty));
}

source : http://daxdude.blogspot.com/2012/11/ax-2012-find-on-hand-inventory-by-date.html

get LedgerDimension combination RecId example code

source : http://kiwiaxguy.blogspot.com/2014/07/setting-ledgerdimension-field-on.html

i modify some code from the source because the dimension name is hardcoded,

on class global :

public static container getDimensionNameTID()
{
    DimensionAttribute              dimAttr;
    DimensionAttributeSetItem       dimAttrSetItem;
    DimensionEnumeration            dimensionSetId;
    DimensionAttributeValue         dimAttributeValue;
    container                       DimensionName;

    dimensionSetId      = DimensionCache::getDimensionAttributeSetForLedger();

    while select dimAttr order by Name
                where dimAttr.Type != DimensionAttributeType::MainAccount
            join RecId from dimAttrSetItem
                where dimAttrSetItem.DimensionAttribute     == dimAttr.RecId &amp;&amp;
                      dimAttrSetItem.DimensionAttributeSet  == dimensionSetId
            {
                dimensionName += dimAttr.Name;

            }

    return DimensionName;
}

getLedgerDimension example code :

public static RecId getLedgerDimensionCombination(MainAccountNum _ledgerAccount, container dimValue)
{
    DimensionServiceProvider DimensionServiceProvider = new DimensionServiceProvider();
    LedgerAccountContract LedgerAccountContract = new LedgerAccountContract();
    DimensionAttributeValueContract   ValueContract;
    List ListValueContract = new List(Types::Class);
    dimensionAttributeValueCombination dimensionAttributeValueCombination;
    DimensionStorage          dimStorage;
    container dimensionName = Global::getDimensionNameTID();
    int       loopDimValue = 1;

    if(conLen(dimValue) > 0)
    {
        while(loopDimValue <= conLen(dimValue))
        {
            ValueContract = new DimensionAttributeValueContract();
            ValueContract.parmName(conPeek(dimensionName,loopDimValue)) ;
            ValueContract.parmValue(conPeek(dimValue,loopDimValue));
            ListValueContract.addEnd(ValueContract);
            loopDimValue++;
        }

        LedgerAccountContract.parmMainAccount(_ledgerAccount);
        LedgerAccountContract.parmValues(ListValueContract);
        dimStorage = DimensionServiceProvider::buildDimensionStorageForLedgerAccount(LedgerAccountContract);
        dimensionAttributeValueCombination = DimensionAttributeValueCombination::find(dimStorage.save());
        return dimensionAttributeValueCombination.RecId;
    }
    else
    {
        return 0;
    }

}

example code on how to use it :

static void TIDF_getLedgerDim(Args _args)
{
    DimensionValue       dim1,dim2;
    container conDimValue;
    MainAccountNum       mainAccountNum;

    mainAccountNum = "6100-1001";
    dim1           = "5102";
    dim2           = "OPERATIO";
    conDimValue = [dim1,dim2];

    info(strFmt("%1",getLedgerDimensionCombination(mainAccountNum,conDimValue)));


}

Init field value from datasource , show on Enterprise Portal AXBoundField

on AOT dataset method init() :
Capture

X++ code on init method example:

public void init()
{
    super();
    DNLLeaveRequest.DNLEmplRecId  = DNLEmployeeTable::findByUserId().RecId;
    DNLLeaveRequest.LeaveDateFrom = today();
    DNLLeaveRequest.LeaveDateTo   = today();
}

or you can code it on Tables\initvalue()

XML code on visual studio for EP pages :

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="TIDDNLLeaveRequestEP.ascx.cs" Inherits="TIDDNLLeaveRequestEP" %>
<dynamics:AxDataSource ID="AxDataSource1" runat="server" 
    DataSetName="TIDLeaveRequestDS" ProviderView="DNLLeaveRequest" 
    oninitializeddatasetrun="AxDataSource1_InitializedDataSetRun">
</dynamics:AxDataSource>
<dynamics:AxForm ID="AxForm1" runat="server" DataSourceID="AxDataSource1" 
    DataKeyNames="RecId,Added,AdvanceUsed,BlankLeave,carryused,ContactPhone,createdBy,createdDateTime,dataAreaId,DNLEmplRecId,DNLLeaveTypeRecId,IdApproval,IdPersonSubstitute,LeaveDateFrom,LeaveDateTo,modifiedBy,modifiedDateTime,Remarks,RequestDate,State,StatusFlag,SubmittedBy,SubmittedDateTime,TableId,TotalLeaveDays,TravellingLocation,getEmplName**,GetEntitlement**,getExpiration**,getLeaveDesc**,mostRecentComment**,requiredActionDueDate**,titleFields**" 
    DataMember="DNLLeaveRequest_Current" AutoGenerateInsertButton="True" 
    DefaultMode="Insert" UpdateOnPostBack="true" oninit="AxForm1_Init"  >
    <dynamics:AxMultiColumn ID="AxMultiColumn1" runat="server">
    
 
    
 
        <dynamics:AxColumn ID="AxColumn2" runat="server">
            <dynamics:AxGroup ID="groupLeaveRequest" runat="server" FormID="AxForm1" 
                Caption="Leave Request" CaptionAlign="Top" HorizontalAlign="Left" 
                Width="300px">
                <Fields>
                    <dynamics:AxReferenceBoundField DataField="DNLEmplRecId" 
                        DataSet="TIDLeaveRequestDS" DataSetView="DNLLeaveRequest" 
                        SortExpression="DNLEmplRecId" Mandatory="True">
                    </dynamics:AxReferenceBoundField>
                    <dynamics:AxReferenceBoundField AutoPostBack="True" 
                        DataField="DNLLeaveTypeRecId" DataSet="TIDLeaveRequestDS" 
                        DataSetView="DNLLeaveRequest" SortExpression="DNLLeaveTypeRecId" 
                        Mandatory="True">
                    </dynamics:AxReferenceBoundField>
                    <dynamics:AxBoundField AutoPostBack="True" DataField="LeaveDateFrom" 
                        DataSet="TIDLeaveRequestDS" 
                        DataSetView="DNLLeaveRequest" SortExpression="LeaveDateFrom">
                    </dynamics:AxBoundField>
                    <dynamics:AxBoundField AutoPostBack="True" DataField="LeaveDateTo" 
                        DataSet="TIDLeaveRequestDS" 
                        DataSetView="DNLLeaveRequest" SortExpression="LeaveDateTo" 
                        Mandatory="True" >
                    </dynamics:AxBoundField>
                    <dynamics:AxBoundField AutoPostBack="True" DataField="Remarks" 
                        DataSet="TIDLeaveRequestDS" DataSetView="DNLLeaveRequest" 
                        SortExpression="Remarks">
                    </dynamics:AxBoundField>
                    <dynamics:AxBoundField AutoPostBack="True" DataField="TotalLeaveDays" 
                        DataSet="TIDLeaveRequestDS" DataSetView="DNLLeaveRequest" 
                        SortExpression="TotalLeaveDays">
                    </dynamics:AxBoundField>
                    <dynamics:AxBoundField DataField="GetEntitlement**" DataSet="TIDLeaveRequestDS" 
                        DataSetView="DNLLeaveRequest" ReadOnly="True">
                    </dynamics:AxBoundField>
                </Fields>
            </dynamics:AxGroup>
        </dynamics:AxColumn>
    </dynamics:AxMultiColumn>
</dynamics:AxForm>

C# code on visual studio for EP pages

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.WebControls;
using Microsoft.Dynamics.Framework.Portal.UI.WebControls;
using Microsoft.Dynamics.Framework.Portal.UI.WebControls.WebParts;
using Microsoft.Dynamics.AX.Framework.Portal.Data;
using Microsoft.Dynamics.AX.Framework.Services.Client;
using Microsoft.Dynamics.Framework.BusinessConnector.Session;
using Microsoft.Dynamics.Framework.BusinessConnector.Adapter;
using Microsoft.Dynamics.Framework.Portal;
using Microsoft.Dynamics.Framework.BusinessConnector.Proxy;

public partial class TIDDNLLeaveRequestEP : System.Web.UI.UserControl
{
    DateTime dateFrom;
    DateTime dateTo;
    Int64 recIdLeaveType;
   
    

    #region customMethod
    private ISession AxSession
    {
        get 
        {
            AxBaseWebPart webPart = AxBaseWebPart.GetWebpart(this);
            return webPart == null ? null : webPart.Session;
        }
    }
    static AxBoundField GetField(DataControlFieldCollection fields, string name)
    {
        foreach (DataControlField field in fields)
        {
            // Is this the field being searched for?
            AxBoundField boundField = field as AxBoundField;
            if (boundField != null && String.Compare(boundField.DataField, name, true) == 0)
            {
                return boundField;
            }

        }
        // Nothing found, so return null.
        return null;
    }

    private DataSetViewRow CurrentRow
    {
        get
        {
            try
            {
                DataSetView dataSetView;
                dataSetView = this.AxDataSource1.GetDataSet().DataSetViews["DNLLeaveRequest"];
                return (dataSetView == null) ? null : dataSetView.GetCurrent();
            }
            catch (System.Exception)
            {
                return null;
            }
        }
    }

    #endregion customMethod

    protected void AxForm1_Init(object sender, EventArgs e)
    {
        //this.loadFirst();
        this.AxForm1.DefaultMode = DetailsViewMode.Insert;
        this.AxForm1.AutoGenerateInsertButton = true;

        AxBoundField axbfNoNPK;
        axbfNoNPK = GetField(groupLeaveRequest.Fields, "DNLEmplRecId");
        axbfNoNPK.ReadOnly = true; 
    }


    protected void Page_Load(object sender, EventArgs e)
    {

    }
 
   
    protected void AxDataSource1_InitializedDataSetRun(object sender, AxDataSourceDataSetEventArgs e)
    {
        e.DataSet.Init();
    }
}

preview :
Capture

Print Query-Based SSRS via X++ example

code example :

public void PrintPenarikanBarang(TECTradeInId tradeInCode)
{
    SrsReportRunController                  reportRunController;
    Map                                     queryContracts;
    MapEnumerator                           mapEnum;
    Query                                   query;
    QueryBuildRange                         range;

    SrsReportDataContract                   contract;
    TECTradeInPenarikanBarangReportContract     rdpContract;

    if(TECTradeInTable.TECTradeInCode)
    {
        reportRunController = new SrsReportRunController();
        reportRunController.parmReportName(ssrsReportStr(TECPenarikanBarangTradeIn ,Report));
        reportRunController.parmLoadFromSysLastValue(false);

        // Set printer settings (print to file, format, filename, etc).
        contract    = reportRunController.parmReportContract();

        rdpContract = contract.parmRdpContract() as TECTradeInPenarikanBarangReportContract;

        queryContracts = contract.parmQueryContracts();
        mapEnum = queryContracts.getEnumerator();
        while(mapEnum.moveNext())
        {
            query = mapEnum.currentValue();
            range = SysQuery::findOrCreateRange(query.dataSourceTable(tableNum(TECTradeInTable)),fieldNum(TECTradeInTable, TECTradeInCode));
            range.value(queryValue(tradeInCode));
        }

        reportRunController.runReport();

    }

}

Modify Query on Report DP Class example

[SysEntryPointAttribute]
public void processReport()
{
    //query class
    QueryRun            qr;
    Query               q;
    QueryBuildDataSource qbds;
    //table object
    InventSum           inventSum;
    WMSLocation         wmsLocation;
    RetailStoreTable    retailStoreTable;
    TIDLocType          tidLocType;
    //
    str                 headerName;

    contract = this.parmDataContract() as TIDStoreDisplayReportContract;
    parmShowQty = contract.parmShowQty();
    parmFilterItem = contract.parmStoreDisplayFilterItem();

    q = this.parmQuery();

    q.dataSourceTable(tableNum(WMSLocation)).addRange(fieldNum(WMSLocation,InventLocationId)).value(TECComputerNameTable::find(xGlobal::computerName()).InventLocationId);
    switch(parmFilterItem)
    {
        case TIDStoreDisplayFilterItem::OnlyDisplay :
            q.dataSourceTable(tableNum(TIDLocType)).addRange(fieldNum(TIDLocType,TIDIsDisplay)).value(SysQuery::value(NoYes::Yes));
            headerName = "Only Display Item";
            break;
        case TIDStoreDisplayFilterItem::NoDisplay :
            qbds = q.dataSourceTable(tableNum(InventSum)).addDataSource(tableNum(TIDStoreHaveDisplayItem));
            qbds.addRange(fieldNum(TIDStoreHaveDisplayItem,InventLocationId)).value(TECComputerNameTable::find(xGlobal::computerName()).InventLocationId);
            qbds.joinMode(JoinMode::NoExistsJoin);
            qbds.relations(false);
            qbds.addLink(fieldNum(InventSum,ItemId),fieldNum(TIDStoreHaveDisplayItem,ItemId));
            headerName = "No Display Item";
            break;
        case TIDStoreDisplayFilterItem::NotInDisplay :
            q.dataSourceTable(tableNum(TIDLocType)).addRange(fieldNum(TIDLocType,TIDIsDisplay)).value(SysQuery::value(NoYes::No));
            headerName = "Not in Display Item";
            break;
        case TIDStoreDisplayFilterItem::HaveDisplay :
            qbds =  q.dataSourceTable(tableNum(InventSum)).addDataSource(tableNum(TIDStoreHaveDisplayItem));
            qbds.addRange(fieldNum(TIDStoreHaveDisplayItem,InventLocationId)).value(TECComputerNameTable::find(xGlobal::computerName()).InventLocationId);
            qbds.joinMode(JoinMode::ExistsJoin);
            qbds.relations(false);
            qbds.addLink(fieldNum(InventSum,ItemId),fieldNum(TIDStoreHaveDisplayItem,ItemId));
            headerName = "Have Display Item";
            break;
        default :
            headerName = "Store Display Item";
            break;
    }

    // only display > 0
    q.dataSourceTable(tableNum(InventSum)).addRange(fieldNum(InventSum,AvailPhysical)).value(queryValue(">0"));

    qr = new QueryRun(q);

    while(qr.next())
    {
        inventSum   = qr.get(tableNum(inventSum));
        wmsLocation = qr.get(tableNum(wmsLocation));
        tidLocType  = qr.get(tableNum(TIDLocType));

        tempTable.clear();
        tempTable.headerName        = headerName;
        tempTable.ItemId            = inventSum.ItemId;
        tempTable.EcoResDescription = TIDItemDisplayCustom::getItemDescription(inventSum.ItemId);
        tempTable.EcoResProductName = TIDItemDisplayCustom::getItemName(inventSum.ItemId);
        tempTable.NameAlias         = TIDItemDisplayCustom::getItemModel(inventSum.ItemId);
        tempTable.AvailPhysical     = inventSum.AvailPhysical;
        select firstOnly retailStoreTable where retailStoreTable.inventLocation == wmsLocation.inventLocationId;
        tempTable.Store             = retailStoreTable.StoreNumber;
        tempTable.WMSLocationId     = wmsLocation.wMSLocationId;
        tempTable.IsDisplay         = tidLocType.TIDIsDisplay;
        tempTable.insert();

    }

}

get currency exchange rate using AX Class

static CurrencyExchangeRate getExchRate(CurrencyCode fromCurrency, CurrencyCode toCurrency, TransDate exchangeDate, RefRecId exchangeRateTypeRecId)
{
    ExchangeRateHelper exchangeRateHelper;
    ;

    exchangeRateHelper = ExchangeRateHelper::construct();
    exchangeRateHelper.parmLedgerRecId(Ledger::current());
    exchangeRateHelper.parmFromCurrency(fromCurrency);
    exchangeRateHelper.parmToCurrency(toCurrency);
    exchangeRateHelper.parmExchangeDate(exchangeDate);
    exchangeRateHelper.parmExchangeRateTypeRecId(exchangeRateTypeRecId);

    return ExchangeRateHelper::displayStoredExchangeRate_Static(exchangeRateHelper.getExchangeRate1(),
           ExchangeRateCurrencyPair::getExchangeRateDisplayFactor(fromCurrency, toCurrency, exchangeRateTypeRecId, true));
}

get exchange rate example code

static void TIDF_ExchangeRate(Args _args)
{
    ExchangeRate     exchangeRate;
    ExchangeRateType ExchangeRateType; 
    ExchangeRateCurrencyPair exchangeRateCurrencyPair;
    real             exchRate;
    
    CurrencyCode fromCurrency  = "USD";
    CurrencyCode toCurrency    = "IDR";
    TransDate    transDate     = today();
    
    
    select firstonly exchangeRateCurrencyPair 
    where 
        exchangeRateCurrencyPair.ExchangeRateType == Ledger::find(Ledger::current()).TECFakturPajakAdjustExchangeRateType
    &&  exchangeRateCurrencyPair.FromCurrencyCode == fromCurrency 
    &&  exchangeRateCurrencyPair.ToCurrencyCode   == toCurrency;
    exchRate = exchangeRate::findByDate(exchangeRateCurrencyPair.RecId,transDate).ExchangeRate;
    info(strFmt("%1",exchRate/100));
    
}

Change caption form via code example

public void init()
{
    super();

    element.updateDesign(InventDimFormDesignUpdate::Init);

    //add by fanddy
    if(element.args().record().TableId == tableNum(TECCustInOutClaimTable))
    {
        TECCustInOutClaimTable = element.args().record();
        element.design().caption(strFmt("Customer Claim Line : %1, Receipt Number : %2",TECCustInOutClaimTable.TECCustInOutClaimId,TECCustInOutClaimTable.RetailReceiptId));
    }

    element.disableNewButton();


}

fix budget exceeded still can submit Ledger Journal WorkFlow , ledgerJournalCheckPost

on class LedgerJournalWFApprSubmitToWF \ main

//add by fanddy, fix Bugs exceed budget still can submit on 30/03/2015
    LedgerJournalCheckPost ledgerJournalCheckPost;
	FormDataSource fds;
    //end add by fanddy


    Debug::assert(tableId == tableNum(LedgerJournalTable));
    Debug::assert(recId != 0);

    // The method has not been called correctly.
    if (tableId != tableNum(LedgerJournalTable) ||
        recId == 0)
    {
        throw error(strFmt("@SYS19306", funcName()));
    }
    //add by fanddy, fix Bugs exceed budget still can submit on 30/03/2015
    else
    {
        ledgerJournalCheckPost= ledgerJournalCheckPost::newLedgerJournalTable(ledgerJournalTable,NoYes::No,NoYes::Yes);
        ledgerJournalCheckPost.run();

        if(!ledgerJournalCheckPost.getParmCheckJournalTID())
        {
            throw error("Can't submit this journal");
        }
		//refresh form dataSource , fix error when submit must restore form dataSource 
		fds = args.record().dataSource();
		fds.research(true);
		fds.refresh();
    }
    //end add by fanddy

i did some modify on class LedgerJournalCheckPost for returning checkJournal result.
on LedgerJournalCheckPost\run method

//edited by fanddy
checkResultTID = this.checkJournal();

set default dimension value

public static RecId getNewDefaultDimension(RecId defaultDimension, Name dimName, str 255 dimValue)
{
    container c;
    RecId newdefaultDimension;
    int i;
    ;

    c = AxdDimensionUtil::getDimensionAttributeValueSetValue(defaultDimension);
    i = conFind(c, dimName);
    if (!i && !dimValue)
        return defaultDimension;
    if (i)
    {
        c = conDel(c, i+1, 1);
        c = conDel(c, i, 1);
    }
    if (dimValue)
    {
        c += dimName;
        c += dimValue;
    }

    c = conDel(c, 1, 1);
    c = conIns(c, 1, conLen(c) / 2);
    newdefaultDimension = AxdDimensionUtil::getDimensionAttributeValueSetId(c);

    return newdefaultDimension;
}

get dimension name , return container

public static container getDimensionName()
{
    DimensionAttribute              dimAttr;
    DimensionAttributeSetItem       dimAttrSetItem;
    DimensionEnumeration            dimensionSetId;
    DimensionAttributeValue         dimAttributeValue;
    container                       DimensionName;

    dimensionSetId      = DimensionCache::getDimensionAttributeSetForLedger();

    while select dimAttr order by Name
                where dimAttr.Type != DimensionAttributeType::MainAccount
            join RecId from dimAttrSetItem
                where dimAttrSetItem.DimensionAttribute     == dimAttr.RecId &amp;&amp;
                      dimAttrSetItem.DimensionAttributeSet  == dimensionSetId
            {
                dimensionName += dimAttr.Name;

            }

    return DimensionName;
}

Custom Number Sequence Reference Example

1. Create new field as picture below

Capture1

2. Go to the form, right click and choose restore to reload new field we added before. On the field method, add code below
 

public Common lookupReference(FormReferenceControl _formReferenceControl)
{
    return NumberSequenceTable::lookupReference(_formReferenceControl);
}

 
Capture2

3. Add reference group for the field at the form as picture below , and you are done.

Capture3

4. Just run the form for testing.

Capture4

Custom lookup example 2

public void lookup()
{
   // super();

    SysTableLookup sysTableLookup = SysTableLookup::newParameters(tablenum(SalesTable), this);
    Query query = new Query();
    QueryBuildDataSource qbds,qbds2,qbds3;

    qbds = query.addDataSource(tablenum(SalesTable));
    qbds.addOrderByField(fieldNum(SalesTable,SalesId));
    qbds.addOrderByField(fieldNum(SalesTable,SalesName));
    qbds.addOrderByField(fieldNum(SalesTable,SalesType));
    qbds.addOrderByField(fieldNum(SalesTable,CustAccount));

    qbds.addGroupByField(fieldNum(SalesTable,SalesId));
    qbds.addGroupByField(fieldNum(SalesTable,SalesName));
    qbds.addGroupByField(fieldNum(SalesTable,SalesType));
    qbds.addGroupByField(fieldNum(SalesTable,CustAccount));
    
    qbds2 = qbds.addDataSource(tableNum(TECDeliveryOrderTable));
    qbds2.joinMode(JoinMode::NoExistsJoin);
    qbds2.relations(false);
    qbds2.addLink(fieldNum(SalesTable,SalesId),fieldNum(TECDeliveryOrderTable,TIDUnlockSalesId));

    qbds3 = qbds.addDataSource(tableNum(SalesLine));
    qbds3.joinMode(JoinMode::InnerJoin);
    qbds3.relations(false);
    qbds3.addLink(fieldNum(SalesTable,SalesId),fieldNum(SalesLine,SalesId));
    qbds3.addRange(fieldNum(SalesLine,ItemId)).value(InventParameters::find().TIDItemIdServices);


    sysTableLookup.addLookupfield(fieldnum(SalesTable, SalesId),true);
    sysTableLookup.addLookupfield(fieldNum(SalesTable,SalesName));
    sysTableLookup.addLookupfield(fieldNum(SalesTable,SalesType));
    sysTableLookup.addLookupfield(fieldNum(SalesTable,CustAccount));
    sysTableLookup.addLookupMethod("customerName");
    sysTableLookup.parmQuery(query);
    sysTableLookup.performFormLookup();

}

Modify AOT items properties via code x++

TreeNode    objTreeNode;
 
objTreeNode = TreeNode::findNode(@"\Menu Items\Display\");
 
if (objTreeNode)
{
    objTreeNode = objTreeNode.AOTfirstChild();
    /*
    change objTreeNode object properties
    */
    while (objTreeNode)
    {            
        objTreeNode.AOTsetProperties("PROPERTIES\n ViewUserLicense  #" + 'TASK' + "\n  MaintainUserLicense  #" + 'TASK' + "\n ENDPROPERTIES\n");
        objTreeNode.AOTsave();
        objTreeNode = objTreeNode.AOTnextSibling();
    }
}

source : http://dotnetxperience.blogspot.com/2012/10/modify-aot-items-from-code-ax-2012.html

Job example using COMVariant

static void TIDF_UploadUnitConversion(Args _args)
{
    //coded by fanddy
    // for upload Unit Conversion Purpose
    SysExcelApplication     application;
    SysExcelWorkbooks       workbooks;
    SysExcelWorkbook        workbook;
    SysExcelWorksheets      worksheets;
    SysExcelWorksheet       worksheet;
    SysExcelCells           cells;
    SysExcelCell            cell;
    COMVariantType          type;
    int                     row;

    UnitOfMeasureConversion UnitOfMeasureConversion;
    //table's field data
    ItemId                  itemid;
    UnitOfMeasureSymbol     unitTo;
    unitOfMeasureSymbol     unitFrom;
    Factor                  factor;



    Filename                fileName = 'C:\\#TECTURA#\\Master Data\\UploadFormula\\UnitConversionrev4.xlsx';

    int                     loop;
    int                     lastSerial = 1;


    application = SysExcelApplication::construct();
    workbooks   = application.workbooks();

    try
    {
        workbooks.open(fileName);
    }
    catch
    {
        throw error(strFmt("File: %1 cannot be opened", fileName));
    }

    workbook    = workbooks.item(1);
    worksheets  = workbook.worksheets();

    worksheet   = worksheets.itemFromNum(1);
    cells       = worksheet.cells();

    row         = 2;
    type        = cells.item(row, 1).value().variantType();

    ttsBegin;
    while (type != COMVariantType::VT_EMPTY)
    {
        itemid      = cells.item(row, 1).value().bStr();
        unitFrom    = cells.item(row, 2).value().bStr();
        unitTo      = cells.item(row, 3).value().bStr();
        factor      = cells.item(row, 4).value().double();

        UnitOfMeasureConversion.clear();
        UnitOfMeasureConversion.Product             = EcoResProduct::findByProductNumber(itemid).RecId;
        UnitOfMeasureConversion.FromUnitOfMeasure   = UnitOfMeasure::findBySymbol(unitFrom).RecId;
        UnitOfMeasureConversion.ToUnitOfMeasure     = UnitOfMeasure::findBySymbol(unitTo).RecId;
        UnitOfMeasureConversion.Factor              = factor;
        UnitOfMeasureConversion.Numerator           = 1;
        UnitOfMeasureConversion.Denominator         = 1;

        UnitOfMeasureConversion.insert();
        row++;
        type    = cells.item(row, 1).value().variantType();
    }
    ttsCommit;
    application.quit();

    info(strFmt('Upload Success'));
}

Create Loyalty Point Customer via X++


static void TIDF_TestCreateLoyaltyPointCustomer(Args _args)
{
    //table
    RetailLoyaltyCustTable      retailLoyaltyCustTable;
    RetailLoyaltyMSRCardTable   retailLoyaltyMSRCardTable;
    RetailLoyaltyMSRCardTrans   retailLoyaltyMSRCardTrans;
    AxRetailLoyaltyMSRCardTable AxRetailLoyaltyMSRCardTable;
    RetailLoyaltySchemesTable   RetailLoyaltySchemesTable;
    
    //field
    RetailLoyaltyCustId     retailLoyaltyCustId;
    CustAccount             custAccount;
    RetailLoyaltySchemeId   retailLoyaltySchemeId;
    RetailLoyaltyCardId     retailLoyaltyCardId;
    RetailLoyaltyPoints     retailLoyaltyPoints;
    
    retailLoyaltyCustId = "XXTESTXX03";
    custAccount         = "010203";
    retailLoyaltySchemeId = "2";
    retailLoyaltyCardId = "XXTESTXX10";
    retailLoyaltyPoints = 50;

    //save header
    retailLoyaltyCustTable.clear();
    retailLoyaltyCustTable.initValue();
    retailLoyaltyCustTable.accountNum = custAccount;
    retailLoyaltyCustTable.initFromCustTable(CustTable::find(custAccount));
    retailLoyaltyCustTable.loyaltyCustId = retailLoyaltyCustId ;
    retailLoyaltyCustTable.insert();

    //save lines
    AxRetailLoyaltyMSRCardTable =  new AxRetailLoyaltyMSRCardTable();
    AxRetailLoyaltyMSRCardTable.parmLoyaltyCustId(retailLoyaltyCustTable.loyaltyCustId);
    AxRetailLoyaltyMSRCardTable.parmLinkId(retailLoyaltyCustTable.loyaltyCustId);

    RetailLoyaltySchemesTable = RetailLoyaltySchemesTable::find(retailLoyaltySchemeId);
    if(RetailLoyaltySchemesTable)
    {
        AxRetailLoyaltyMSRCardTable.parmLoyaltySchemeId(RetailLoyaltySchemesTable.loyaltySchemeId);
    }

    AxRetailLoyaltyMSRCardTable.parmLoyaltyTender(RetailLoyaltyTenderTypeBase::AsCardTender);
    AxRetailLoyaltyMSRCardTable.parmCardNumber(retailLoyaltyCardId);
    AxRetailLoyaltyMSRCardTable.save();
    
    //upload points.
    retailLoyaltyMSRCardTrans.clear();
    retailLoyaltyMSRCardTrans.loyaltySchemeId = RetailLoyaltySchemesTable.loyaltySchemeId;
    retailLoyaltyMSRCardTrans.loyaltyCustId   = retailLoyaltyCustId;
    retailLoyaltyMSRCardTrans.cardNumber      = AxRetailLoyaltyMSRCardTable.retailLoyaltyMSRCardTable().cardNumber;
    retailLoyaltyMSRCardTrans.entryType       = RetailLoyaltyEntryTypeBase::Sale;
    retailLoyaltyMSRCardTrans.expirationDate  = maxDate();
    retailLoyaltyMSRCardTrans.points          = retailLoyaltyPoints;
    //include store or staff or any
    //retailLoyaltyMSRCardTrans.storeId   
    
    retailLoyaltyMSRCardTrans.insert();


}

lookup using view example x++

 
Capture
 

public void lookup()
{

     QueryBuildDataSource queryBuildDataSource;
    //super();
    //coded by fanddy, 
     SysTableLookup sysTableLookup = SysTableLookup::newParameters(tablenum(TIDInventLookup), this);

     Query query = new Query();

     queryBuildDataSource = query.addDataSource(tableNum(TIDInventLookup));
     sysTableLookup.addLookupfield(fieldnum(TIDInventLookup,NameAlias));
     sysTableLookup.addLookupfield(fieldnum(TIDInventLookup,DisplayProductNumber));
     sysTableLookup.addLookupfield(fieldnum(TIDInventLookup,Name));
     sysTableLookup.parmQuery(query);
     sysTableLookup.performFormLookup();

}

Speeding up Sales Agreement Release Order process

When we create SO from sales agreement, we will face a problem that occur on standard version of AX 2012 if number of sales agreement record are thousands and we only want to choose let’s say 2 or 3 line from sales agreement line to Sales Line.
 
we can choose records from agreement line by fill the quantity, and the problem is standard AX still will loop all records no matter the quantity is fill or not. and all thosands will going through process that not needed.
 
Class : SalesAutoCreate\Create

void  create()
{
    #OCCRetryCount

    try
    {
        setprefix("@SYS55110");

        ttsbegin;

        while (this.recordExist())
        {

            this.setCust();

            setprefix(#PreFixField(CustTable,AccountNum));

            this.setSalesTable();

            this.setSalesLine();

            setprefix(#PreFixField(SalesLine,ItemId));

            this.nextRecord();
        }

        this.endUpdate();

        ttscommit;
    }

    catch (Exception::Deadlock)
    {
        retry;
    }

    catch (Exception::UpdateConflict)
    {
        if (appl.ttsLevel() == 0)
        {
            if (xSession::currentRetryCount() >= #RetryNum)
            {
                throw Exception::UpdateConflictNotRecovered;
            }
            else
            {
                retry;
            }
        }
        else
        {
            throw Exception::UpdateConflict;
        }
    }

}

i tried debug and i found the issue that made sales agreement release order process become so slow. and made a modification as below.
Class : SalesAutoCreate_ReleaseFromAgreement\New

protected void new(Common  _releaseOrderLine,
                   Object  _callBackClass     = null,
                   Common  _releaseOrderTable = null)
{
    //modify by fanddy
    //purpose : speeding up release agreement from BMP
    SalesCreateReleaseOrderLineTmp  TIDSalesCreateReleaseOrderLineTmp;

    releaseOrderLine     = _releaseOrderLine  as SalesCreateReleaseOrderLineTmp;
    delete_from releaseOrderLine where releaseOrderLine.SalesQty < 1;
    //end modify fanddy

    releaseOrderTable    = _releaseOrderTable as SalesCreateReleaseOrderTableTmp;
    this.firstRecord();

    createFromAgreementLine     = AgreementLineQuantityCommitment::find(releaseOrderLine.AgreementLineQuantityCommitment, false);
    createFromSalesAgreement    = SalesAgreementHeader::find(createFromAgreementLine.Agreement ? createFromAgreementLine.Agreement : releaseOrderTable.AgreementHeader);

    currentSalesId       = '';
    firstRecord          = true;

    super(_releaseOrderLine,_callBackClass);
    // <GEERU>
    countryRegion_RU = SysCountryRegionCode::isLegalEntityInCountryRegion([#isoRU]);
    // </GEERU>

 

Voila !! Now your when you create an SO with 2-3 SO lines originated from thousands line data of sales agreement, the process has been boosted !!

print report via x++ AX 2012

SrsReportRunController          controller = new SrsReportRunController();
SysUserLicenseCountRDPContract  rdpContract = new SysUserLicenseCountRDPContract();
SRSPrintDestinationSettings     settings;
 
// Define report and report design to use
controller.parmReportName(ssrsReportStr(SysUserLicenseCountReport, Report));
// Use execution mode appropriate to your situation
controller.parmExecutionMode(SysOperationExecutionMode::ScheduledBatch);
// Suppress report dialog
controller.parmShowDialog(false);
 
// Explicitly provide all required parameters
rdpContract.parmReportStateDate(systemDateGet());
controller.parmReportContract().parmRdpContract(rdpContract);
 
// Change print settings as needed
settings = controller.parmReportContract().parmPrintSettings();
settings.printMediumType(SRSPrintMediumType::File);
settings.fileFormat(SRSReportFileFormat::Excel);
settings.fileName(@'\\share\UserLicenseCount.xlsx');
 
// Execute the report
controller.startOperation();

Upload a LedgerJournalTrans Fixed Asset type without insert to LedgerJournalTrans_Asset table

an error will occured when you try validate ledgerJournalTrans.

how to fix this :

static void TIDF_fixBugsUploadFixedAssets(Args _args)
{
    ledgerjournaltrans ledgerJournalTrans;
    LedgerJournalTrans_Asset    cekExist;
    LedgerJournalTrans_Asset    LedgerJournalTrans_Asset;
    
    while select  ledgerJournalTrans 
    where 
        ledgerJournalTrans.JournalNum == 'GEN-000007'
    {
        select cekExist where cekExist.RefRecId == ledgerJournalTrans.RecId;
        
         if (ledgerJournalTrans.isFixedAssetsTransaction() && !cekExist)
            {
                ledgerJournalTrans_Asset.clear();
                ledgerJournalTrans_Asset.initValue();

                ledgerJournalTrans_Asset.RefRecId  = ledgerJournalTrans.RecId;
                ledgerJournalTrans_Asset.AssetId   = ledgerJournalTrans.getAssetId();
                ledgerJournalTrans_Asset.Company   = ledgerJournalTrans.getAssetCompany();
                ledgerJournalTrans_Asset.TransType = AssetTransTypeJournal::Acquisition;
                ledgerJournalTrans_Asset.BookId    = "ALL";

                if (!ledgerJournalTrans_Asset.validateWrite())
                    throw Exception::Error;

                ledgerJournalTrans_Asset.insert();
            }
    }


}

source : http://www.cnblogs.com/Fandyx/p/3343688.html

Modify Query Ranges on Report Controller Class

Create a enum and set it on menu item properties as example below.
 
Capture
 
override method preRunModifyContract on report controller class as example code below.

protected void preRunModifyContract()
{
    //modify the parameter value of the contract
   // if( element.args().parmEnumType() == EnumNum( NoYes ) )
    if(this.parmArgs().parmEnumType() == enumNum(TIDSalesDailyRecon))
    {
       switch(this.parmArgs().parmEnum())
       {
           case  TIDSalesDailyRecon::SalesInvoice :
               SrsReportHelper::addParameterValueRangeToQuery(this.getFirstQuery(),tableNum(RetailTransactionPaymentTrans),fieldNum(RetailTransactionPaymentTrans, RecId),SysQuery::value(5637149251));
               break;
           case  TIDSalesDailyRecon::SalesReturn :
               SrsReportHelper::addParameterValueRangeToQuery(this.getFirstQuery(),tableNum(RetailTransactionPaymentTrans),fieldNum(RetailTransactionPaymentTrans, RecId),SysQuery::value(this.parmArgs().record().RecId));
               break;
           case TIDSalesDailyRecon::SalesExIndent :
               break;
       }
    }
}

 
this.parmArgs().record().RecId value is come from :

 SrsReportRunController  controller;
 Args = new Args()

 controller = new SrsReportRunController();
 args.record(TABLES_record);
 controller.parmReportName(ssrsReportStr(REPORT_NAME, REPORT_DESIGN_NAME));

 controller.startOperation();

 
source :
1. http://www.dynamics101.com/2014/01/using-controller-class-developing-ssrs-reports-microsoft-dynamics-ax-2012/
2. http://dynamics.folio3.com/x-tips-and-tricks-passing-parameters-microsoft-dynamics-ax/

add mainAccount to LedgerJournalReport

add this code below to LedgerJournalDP\InsertLedgerJournalTmp

 if(_accountOffsetAccount ==  AccountOffsetaccount::Account)
    {
        switch(_ledgerJournalTrans.AccountType)
        {
            case LedgerJournalACType::Ledger :
                    ledgerJournalTmp.TIDMainAccountId = MainAccount::find(DimensionAttributeValueCombination::find(_ledgerJournalTrans.LedgerDimension).MainAccount).MainAccountId;
                    break;
            case LedgerJournalACType::Bank :
                    select * from dimAttrValueCombo
                    join Name from bankAccountTable
                    where bankAccountTable.AccountID == dimAttrValueCombo.DisplayValue
                    && dimAttrValueCombo.RecId == _ledgerJournalTrans.LedgerDimension;
                    ledgerJournalTmp.TIDMainAccountId = MainAccount::find(DimensionAttributeValueCombination::find(bankAccountTable.LedgerDimension).MainAccount).MainAccountId;
                    ledgerJournalTmp.AccountName = strFmt("%1 : %2",dimAttrValueCombo.DisplayValue, bankAccountTable.Name);
                    break;
            case LedgerJournalACType::Vend :
                    select firstOnly  dimAttrValueCombo  where dimAttrValueCombo.RecId == _ledgerJournalTrans.LedgerDimension;
                    VendLedgerAccounts   = VendLedgerAccounts::find(_ledgerJournalTrans.PostingProfile,TableGroupAll::GroupId,VendTable::find(dimAttrValueCombo.DisplayValue).VendGroup);
                    ledgerJournalTmp.TIDMainAccountId =  MainAccount::find(DimensionAttributeValueCombination::find(VendLedgerAccounts.SummaryLedgerDimension).MainAccount).MainAccountId;
                    ledgerJournalTmp.AccountName = strFmt("%1 : %2",dimAttrValueCombo.DisplayValue,VendTable::find(dimAttrValueCombo.DisplayValue).name());
                    break;
            case LedgerJournalACType::Cust :
                    select firstOnly  dimAttrValueCombo  where dimAttrValueCombo.RecId == _ledgerJournalTrans.LedgerDimension;
                    CustLedgerAccounts = CustLedgerAccounts::find(_ledgerJournalTrans.PostingProfile,TableGroupAll::GroupId,VendTable::find(dimAttrValueCombo.DisplayValue).VendGroup);
                    ledgerJournalTmp.TIDMainAccountId =  MainAccount::find(DimensionAttributeValueCombination::find(CustLedgerAccounts.SummaryLedgerDimension).MainAccount).MainAccountId;
                    ledgerJournalTmp.AccountName = strFmt("%1 : %2",dimAttrValueCombo.DisplayValue,CustTable::find(dimAttrValueCombo.DisplayValue).name());
                    break;
            case LedgerJournalACType::FixedAssets :
                    select firstOnly  dimAttrValueCombo  where dimAttrValueCombo.RecId == _ledgerJournalTrans.LedgerDimension;
                    selecT firstOnly ledgerJournalTrans_asset where ledgerJournalTrans_asset.RefRecId == _ledgerJournalTrans.RecId;
                    assetLedgerAccounts = AssetLedgerAccounts::find(ledgerJournalTrans_asset.BookId,_ledgerJournalTrans.PostingProfile,enum2int(ledgerJournalTrans_asset.TransType),TableGroupAll::GroupId,AssetTable::find(dimAttrValueCombo.DisplayValue).AssetGroup);
                    ledgerJournalTmp.TIDMainAccountId =  MainAccount::find(DimensionAttributeValueCombination::find(assetLedgerAccounts.LedgerDimension).MainAccount).MainAccountId;
                    break;
        }
    }
    else
    {
        switch(_ledgerJournalTrans.AccountType)
        {
            case LedgerJournalACType::Ledger :
                    ledgerJournalTmp.TIDMainAccountId = MainAccount::find(DimensionAttributeValueCombination::find(_ledgerJournalTrans.LedgerDimension).MainAccount).MainAccountId;
                    break;
            case LedgerJournalACType::Bank :
                    select * from dimAttrValueCombo
                    join Name from bankAccountTable
                    where bankAccountTable.AccountID == dimAttrValueCombo.DisplayValue
                    && dimAttrValueCombo.RecId == _ledgerJournalTrans.LedgerDimension;
                    ledgerJournalTmp.TIDMainAccountId = MainAccount::find(DimensionAttributeValueCombination::find(bankAccountTable.LedgerDimension).MainAccount).MainAccountId;
                    ledgerJournalTmp.AccountName = strFmt("%1 : %2",dimAttrValueCombo.DisplayValue, bankAccountTable.Name);
                    break;
            case LedgerJournalACType::Vend :
                    select firstOnly  dimAttrValueCombo  where dimAttrValueCombo.RecId == _ledgerJournalTrans.LedgerDimension;
                    VendLedgerAccounts   = VendLedgerAccounts::find(VendParameters::find().PostingProfile,TableGroupAll::GroupId,VendTable::find(dimAttrValueCombo.DisplayValue).VendGroup);
                    ledgerJournalTmp.TIDMainAccountId =  MainAccount::find(DimensionAttributeValueCombination::find(VendLedgerAccounts.SummaryLedgerDimension).MainAccount).MainAccountId;
                    ledgerJournalTmp.AccountName = strFmt("%1 : %2",dimAttrValueCombo.DisplayValue,VendTable::find(dimAttrValueCombo.DisplayValue).name());
                    break;
            case LedgerJournalACType::Cust :
                    select firstOnly  dimAttrValueCombo  where dimAttrValueCombo.RecId == _ledgerJournalTrans.LedgerDimension;
                    CustLedgerAccounts = CustLedgerAccounts::find(CustParameters::find().PostingProfile,TableGroupAll::GroupId,VendTable::find(dimAttrValueCombo.DisplayValue).VendGroup);
                    ledgerJournalTmp.TIDMainAccountId =  MainAccount::find(DimensionAttributeValueCombination::find(CustLedgerAccounts.SummaryLedgerDimension).MainAccount).MainAccountId;
                    ledgerJournalTmp.AccountName = strFmt("%1 : %2",dimAttrValueCombo.DisplayValue,CustTable::find(dimAttrValueCombo.DisplayValue).name());
                    break;
            case LedgerJournalACType::FixedAssets :
                    select firstOnly  dimAttrValueCombo  where dimAttrValueCombo.RecId == _ledgerJournalTrans.LedgerDimension;
                    selecT firstOnly ledgerJournalTrans_asset where ledgerJournalTrans_asset.RefRecId == _ledgerJournalTrans.RecId;
                    assetLedgerAccounts = AssetLedgerAccounts::find(ledgerJournalTrans_asset.BookId,AssetParameters::find().PostingProfile,enum2int(ledgerJournalTrans_asset.TransType),TableGroupAll::GroupId,AssetTable::find(dimAttrValueCombo.DisplayValue).AssetGroup);
                    ledgerJournalTmp.TIDMainAccountId =  MainAccount::find(DimensionAttributeValueCombination::find(assetLedgerAccounts.LedgerDimension).MainAccount).MainAccountId;
                    break;
        }
    }

Filter Query Form DataSource using DynaLink

example code on form VendPurchaseOrderJournal , datasource VendPurchOrderJournal method init()

public void init()
{
    QueryBuildDataSource  queryDataSourceLink;
    super();

    if (element.args().dataset() == tablenum(PurchReqLine))
    {
        this.query().dataSourceTable(tablenum(VendPurchOrderJour)).clearDynalinks();

        queryDataSourceLink = this.query().dataSourceName(identifierstr(VendPurchOrderJour));
        queryDataSourceLink.relations(true);
        queryDataSourceLink.addDynalink(fieldnum(VendPurchOrderJour, PurchId),
                                        element.args().record(),
                                        fieldnum(PurchReqLine, PurchId));
    }

    //add by fanddy , for inqueries confirm PO
    if (element.args().dataset() == tablenum(TECPOGroupHeader))
    {
        this.query().dataSourceTable(tablenum(VendPurchOrderJour)).clearDynalinks();

        queryDataSourceLink = this.query().dataSourceName(identifierstr(VendPurchOrderJour));
        queryDataSourceLink.relations(true);
        queryDataSourceLink.addDynalink(fieldnum(VendPurchOrderJour, TIDPOGroupId),
                                        element.args().record(),
                                        fieldnum(TECPOGroupHeader, POGroupId));
    }
    //END
}

Found a BudgetPlanningProcessTmp record instead of an expected BudgetPlanningProcess record.

Version : AX 2012 R2 CU7
&nbsp
Found this error this morning when select a record in budgetplanning lookup.
 
Error detail :
 
“Found a BudgetPlanningProcessTmp record instead of an expected BudgetPlanningProcess record. Check to see if an override of the resolveReference method is returning a record from the correct table.”
 
Capture
 
Solution :
 
Revert static method BudgetPlanGenerateBudgetTrnsForm::lookupBudgetPlanningProcess back to SYS layer using compare.

add filter to form datasource method:ExecuteQuery example code

public void executeQuery()
{
    ;
    TECPOGroupHeader_ds.query().dataSourceTable(tableNum(TECPOGroupHeader)).clearRanges();
    if(statusFilter.valueStr() == enum2str(TEC_AllDraftPosted::Draft))
        TECPOGroupHeader_ds.query().dataSourceTable(tableNum(TECPOGroupHeader)).addRange(fieldnum(TECPOGroupHeader,Status)).value(sysquery::value(TECPOGroupStatus::Draft));
    if(statusFilter.valueStr() == enum2str(TEC_AllDraftPosted::Posted))
        TECPOGroupHeader_ds.query().dataSourceTable(tableNum(TECPOGroupHeader)).addRange(fieldnum(TECPOGroupHeader,Status)).value(sysquery::value(TECPOGroupStatus::Posted));
    //add by fanddy
    if(statusFilter.valueStr() == enum2str(TEC_AllDraftPosted::Confirmed))
        TECPOGroupHeader_ds.query().dataSourceTable(tableNum(TECPOGroupHeader)).addRange(fieldnum(TECPOGroupHeader,Status)).value(sysquery::value(TECPOGroupStatus::Confirmed));
    //END add by fanddy
    if(CreatorFilter.value() == true)
        TECPOGroupHeader_ds.query().dataSourceTable(tableNum(TECPOGroupHeader)).addRange(fieldnum(TECPOGroupHeader,CreatedBy)).value(sysquery::value(curUserId()));
    super();
}

get Dimension Value from DefaultDimension

public static str 255 getDimensionValueTID(RecId defaultDimension, Name dimName)
{
    DimensionAttributeValueSetStorage dimStorage;
    ;

    dimStorage = DimensionAttributeValueSetStorage::find(defaultDimension);

    return dimStorage.getDisplayValueByDimensionAttribute(DimensionAttribute::findByName(dimName).RecId);
}

 
how to use :
 
getDimensionValueTID(_ledgerJournalTrans.DefaultDimension, 'BusinessUnit')

Global Variable in X++ AX 2012

some circumtances i must use global variable.

read :
http://msdn.microsoft.com/en-us/library/aa891830.aspx

more example how to use :

SysGlobalCache globalCache;
globalCache = ClassFactory.globalCache();
globalCache.set(strFmt("%1%2",curUserId(),"WhatEver"), 0, "ANY VALUE");

on other class.

SysGlobalCache globalCache;
globalCache = ClassFactory.globalCache();
info(strFmt("%1",globalCache.get(strFmt("%1%2",curUserId(),"WhatEver"), 0)));

Auto Convert field from Excel to X++

public static str COMVariant2Str(COMVariant _cv, int _decimals = 0, int _characters = 0, int _separator1 = 0, int _separator2 = 0)
{
    switch (_cv.variantType())
    {

        case (COMVariantType::VT_BSTR): return _cv.bStr();
        case (COMVariantType::VT_R4): return num2str(_cv.float(),_characters,_decimals,_separator1,_separator2);
        case (COMVariantType::VT_R8): return num2str(_cv.double(),_characters,_decimals,_separator1,_separator2);
        case (COMVariantType::VT_DECIMAL): return num2str(_cv.decimal(),_characters,_decimals,_separator1,_separator2);
        case (COMVariantType::VT_DATE): return date2str(_cv.date(),123,2,1,2,1,4);
        case (COMVariantType::VT_EMPTY): return '';

        default: throw error(strfmt('@SYS26908', _cv.variantType()));
    }
    return '';
}

how to use example :
YourClass::COMVariant2Str(cells.item(row,17).value());

Create Journal Upload with Batch Form

Capture

just duplicate class tutorial_runBaseBatch, then modify the following class :

on class declaration :

public class JournalUploadExcextends RunBaseBatch
{
    DialogField         dfFileName;
    FileName            fileName  ;

    #define.CurrentVersion(1)
    #define.Version1(1)
    #localmacro.CurrentList
        fileName
    #endmacro
}

on dialog() :

public Object dialog()
{
    #File
    DialogRunbase       dialog = super();
    #resAppl
    ;
    dfFileName = dialog.addFieldValue(extendedTypeStr(FileNameOpen),fileName);
    dialog.filenameLookupFilter(["All files", #AllFiles]);

    return dialog;
}

on method getFromDialog() :

public boolean getFromDialog()
{
    //do what ever you want in this class. i call upload journal method with PathFile as parameter
    JournalUploadExc::JournalUpload(dfFileName.value());
    return super();
}

voila.. !! done.. !!

Job Upload General Journal from excel

public static boolean JournalUpload(str _filePath)
{
    container            accEntryPattern;
    container            offSetEntryPattern;

    LedgerJournalACType LedgerJournalACType;
    ledgerJournalName ledgerJournalName;
    journalID JournalID;
    axLedgerJournalTable axLedgerJournalTable;
    axledgerJournalTrans axLedgerJournalTrans;
    LedgerJournalType JournalType = ledgerJournalType::Daily;


    SysExcelApplication                         application = SysExcelApplication::construct();
    SysExcelWorkbooks                           workbooks   = application.workbooks();
    SysExcelWorkbook                            workbook;
    SysExcelWorksheets                          workSheets;
    SysExcelWorksheet                           workSheet;
    SysExcelCells                               cells;
    SysExcelCell                                cell;
    int                                         row;
    str                                         filename, numSeq;

    boolean         _return = true;
    ;


    startLengthyOperation();
    //filename = "C:\\GJCashBank30April2013.xlsx";
    filename = _filePath;

    try
    {
        if (workbooks.open(filename, false /*Update links*/, true /*Read only*/))
        {
            workbook   = workbooks.item(1);
            workSheets = workbook.worksheets();
            workSheet  = workSheets.itemFromNum(1); //worksheet keberapa dari excel di mulai dari angka 1
            cells      = workSheet.cells();

            row = 5;

            ttsBegin;
            axLedgerJournalTable = new axLedgerJournalTable();
            axLedgerJournalTable.parmJournalName("GenJrn");
            axLedgerJournalTable.parmJournalType(JournalType);
            axLedgerJournalTable.parmName("General Journal");
            axLedgerJournalTable.save();
            JournalID = axLedgerJournalTable.parmJournalNum();

            while (cells.item(row,2).value().bStr() != "")
            {
                //Create Trans ...
                axLedgerJournalTrans = new axLedgerJournalTrans();
                axLedgerJournalTrans.parmJournalNum(JournalID);

                //start from A
                axLedgerJournalTrans.parmTransDate(cells.item(row,1).value().date());
                axLedgerJournalTrans.parmAccountType(  str2Enum(LedgerJournalACType, cells.item(row,2).value().bStr()));

                if(cells.item(row,2).value().bStr() == "Ledger")
                {

                    accEntryPattern =
                    [   cells.item(row, 3).value().bStr() + "-" + "Disp",
                        cells.item(row, 3).value().bStr(),
                        4,
                        "BusinessUnit",
                        cells.item(row,17).value().bStr(),
                        "Department",
                        cells.item(row,18).value().bStr(),
                        "ProductCode",
                        cells.item(row,19).value().bStr(),
                        "ProjectCode",
                        cells.item(row,20).value().bStr()
                    ];
                    axLedgerJournalTrans.parmLedgerDimension(AxdDimensionUtil::getLedgerAccountId(accEntryPattern));
                }

                if(cells.item(row,5).value().double() != 0)
                {
                    axLedgerJournalTrans.parmAmountCurDebit(cells.item(row,5).value().double());
                }

                if(cells.item(row,6).value().double() != 0)
                {
                        axLedgerJournalTrans.parmAmountCurCredit(cells.item(row,6).value().double());
                }

                axLedgerJournalTrans.parmtxt(cells.item(row,7).value().bStr());
                axLedgerJournalTrans.parmOffsetAccountType(  str2Enum(LedgerJournalACType,cells.item(row,6).value().bStr()));

                if(cells.item(row,8).value().bStr() == "Ledger")
                {
                    offSetEntryPattern =
                    [   cells.item(row, 9).value().bStr() + "-" + "Disp",
                        cells.item(row, 9).value().bStr(),
                        4,
                        "BusinessUnit",
                        cells.item(row,17).value().bStr(),
                        "Department",
                        cells.item(row,18).value().bStr(),
                        "ProductCode",
                        cells.item(row,19).value().bStr(),
                        "ProjectCode",
                        cells.item(row,20).value().bStr()
                    ];
                    axLedgerJournalTrans.parmOffsetLedgerDimension(AxdDimensionUtil::getLedgerAccountId(offSetEntryPattern));
                }
                //
                axLedgerJournalTrans.parmCurrencyCode(cells.item(row,10).value().bStr());
                axLedgerJournalTrans.parmExchRate(cells.item(row,11).value().double());
                axLedgerJournalTrans.parmInvoice(cells.item(row,12).value().bStr());
                axLedgerJournalTrans.parmPaymReference(cells.item(row,13).value().bStr());
                axLedgerJournalTrans.parmBankTransType(cells.item(row,14).value().bStr());
                axLedgerJournalTrans.parmDocumentNum(cells.item(row,15).value().bStr());
                axLedgerJournalTrans.parmDocumentDate(cells.item(row,16).value().date());
                //

                axLedgerJournalTrans.save();
                row++;

                ttsCommit;
            }

            info('Imported  Items');
        }
    }
    catch(Exception::Error)
    {
        _return = false;
    }

    return _return;
}

File Path X++ AX 2012

static void  main(Args  _args)
{
    FileName            fileName  ;
    container           c;
    FileIOPermission    permission;
    TextBuffer          textBuffer;
    str                 readText;
    str                 readLine;
    int                 etgline;
    int                 i = 0;
    Dialog              dialog = new Dialog("Journal Upload Excel");
    DialogField         dfFileName;
    str 100            filename2;
    container       con;
    ;
    #File

    dfFileName = dialog.addField(extendedTypeStr(FileNameOpen));
    dialog.filenameLookupFilter(["All files", #AllFiles]);

    if (dialog.run())
    {
        fileName = dfFileName.value();
        info(filename);

   }
}

Create Purchase Order via X++

void clicked()
{
    PurchTable  purchTable;
    PurchLine   purchLine;
    InventDim   inventDim;
    NumberSeq   numberSeq;

    //add by fanddy
    AxPurchTable    axPurchTable;
    AxPurchLine     axPurchLine;
    PurchFormLetter purchformLetter;
    //END

   //create PO Header
   purchTable.clear();
   purchTable.initFromVendTable(VendTable::find(TECPOGroupHeader.VendAccount));
   purchTable.DefaultDimension = InventTable::find(POGroupLine.ItemId).DefaultDimension;

   axPurchTable = axPurchTable::newPurchTable(purchTable);
   axPurchTable.parmPurchId(NumberSeq::newGetNum(PurchParameters::numRefPurchId()).num());
   axPurchTable.parmPurchaseType(PurchaseType::Purch);
   axPurchTable.parmDocumentStatus(DocumentStatus::PurchaseOrder);
   axPurchTable.parmAccountingDate(systemDateGet());
   axPurchTable.parmDeliveryDate(systemDateGet());
   axPurchTable.parmPurchStatus(PurchStatus::Backorder);
   axPurchTable.save();

   info(strFmt('Create PO %1', Purchtable.PurchId));

   //create PO Line
   purchLine.clear();
   purchLine.initValue();
   purchLine.initFromPurchTable(purchTable);
   purchLine.initFromInventTable(InventTable::find(POGroupLine2.ItemId));
   axPurchLine = AxPurchLine::newPurchLine(purchLine);
   axpurchLine.parmItemId('YOUR ITEMID');
   axPurchLine.parmPurchQty(YOUR QTY);
   axPurchLine.parmPurchPrice(YOUR PRICE);
   axPurchLine.parmInventDimId('YOUR INVENTDIMID');
   axPurchLine.save();

}

Auto Allocate Charges before auto Confirm Purchase Order

static void AutoAllocateCharges_beforeConfirmPO(Args _args)
{
    PurchTable purchTable;
    PurchFormLetter purchFormLetter;
    Args args = new Args();
    MarkupAllocation markupAllocation;

    select firstOnly purchTable where purchTable.PurchId=='1016-PO-14-000191';
    args.record(purchTable);
    //auto allocate charges
    markupAllocation = MarkupAllocation::newMarkupAllocation(args.record());
    markupAllocation.run(args.parmObject());
    
    purchFormLetter = PurchFormLetter::construct(DocumentStatus::PurchaseOrder);
    purchFormLetter.update(purchTable, purchTable.PurchId);
}

Modify Controller Class for Query Based Report SSRS

public void prePromptModifyContract()
{
    //add a range in the report query  
      SrsReportHelper::addParameterValueRangeToQuery(this.getFirstQuery(),tableNum(SSRSReportDemo),fieldNum(SSRSReportDemo, RecId),SysQuery::value(this.parmArgs().record().RecId));
}

source : https://community.dynamics.com/ax/b/dynamics101trainingcenterax/archive/2014/01/30/using-controller-class-in-developing-ssrs-reports-in-microsoft-dynamics-ax-2012.aspx

get product-category Descendants example

public FreeText getDecendants(ItemId _itemid)
{
    str Decendants;
    EcoResProductCategory ecoResProductCategory;
    EcoResCategory        ecoResCategory;

    EcoResCategory        ecoResCategoryAscendants;

    select firstOnly ecoResProductCategory
    where
        ecoResProductCategory.Product==EcoResProduct::findByProductNumber(_itemid).RecId;

    select firstOnly ecoResCategory where ecoResCategory.RecId==ecoResProductCategory.Category;
    Decendants = ecoResCategory.Name;
    while select * from ecoResCategoryAscendants
            order by ecoResCategoryAscendants.NestedSetRight
                where   ecoResCategoryAscendants.CategoryHierarchy == EcoResCategory.CategoryHierarchy
                        && ecoResCategoryAscendants.NestedSetLeft  < EcoResCategory.NestedSetLeft
                        && ecoResCategoryAscendants.NestedSetRight > EcoResCategory.NestedSetRight
    {
       Decendants = strFmt("%1-%2",ecoResCategoryAscendants.Name,Decendants);
    }


    return Decendants;
}

using “update_record” instead of “while select forupdate”

description on MSDN :
“This means that certain tasks may have improved performance by using the power of the SQL server.”

replace code below for a better perfomance.

MyTable myTableBuffer;
;
while select forUpdate mytableBuffer
{
mytableBuffer.field1 = field * 1.10;
}

with


MyTable myTableBuffer;
;
update_recordset myTableBuffer
setting field1 = field1 * 1.10;

source : http://msdn.microsoft.com/en-us/library/aa674382.aspx

How to print barcode Label , SSRS can’t print on Landscape Printer AX 2012r2

Hi there ,
after the report being save to PDF on local drive, i call adobe to print barcode,
i have to did that, because SSRS can’t print on landscape printer.

here is my example code

void clicked()
{
    //AIFD_PrintBarcode
    AI_PrintBarcodeController  aiBarcode = new AI_PrintBarcodeController();
    AI_PrintBarcodeContract    aiContract = new AI_PrintBarcodeContract();
    ProdJournalProd            prodJournalProdLoc;
    SRSPrintDestinationSettings  printSettings = new SRSPrintDestinationSettings();
    PrintJobSettings    printJobSettings = new PrintJobSettings();
    Dialog              dialog = new Dialog();
    DialogField         dialogFileName;
    str                 adobeExe;
    str                 adobeParm;

    str                 fileName;
    int                 fileCount;

    //AIFD
    InteropPermission   permission;
    str errorMessage;
    //END
    real WeightInreal;
    permission = new InteropPermission(InteropKind::ClrInterop);
    permission.assert();

    super();
    try
    {
        prodJournalProdLoc = ProdJournalProd_ds.getFirst(true);

        while (prodJournalProdLoc)
        {
            fileCount++;
            aiBarcode.parmReportName(ssrsReportStr(AI_PrintBarcoderReport,Report));
            aiBarcode.parmShowDialog(false);
            aiContract.parmRecordId(prodJournalProdLoc.RecId);
            aiContract.parmDocumentTitle(&quot;x&quot;);

            //printSettings = aiBarcode.parmReportContract().parmPrintSettings();
            printSettings.printMediumType(SRSPrintMediumType::File);
            //printSettings.landscape(false);
            //printSettings.printerPageSettings('KRRLabelBarcode');
            //info(strFmt(&quot;%1&quot;,printSettings.printerPageSettings()));

            fileName = strFmt(&quot;D:\\barcode%1.pdf&quot;,fileCount);

            printSettings.fileFormat(SRSReportFileFormat::PDF);
            printSettings.fileName(fileName);
            printSettings.printerName(&quot;TOSHIBA B-SA4TP TS&quot;);
            printSettings.landscape(false);
            printSettings.overwriteFile(true);
            aiBarcode.parmReportContract().parmRdpContract(aiContract);
            aiBarcode.parmReportContract().parmPrintSettings(printSettings);

            aiBarcode.startOperation();

            WeightInReal = sleep(500);
            //printJobSettings.printerSettings('SysPrintForm');
            printJobSettings.setTarget(PrintMedium::Printer);
            printJobSettings.preferredTarget(PrintMedium::Printer);
            adobeExe = WinAPI::findExecutable(fileName);

            adobeParm = strFmt(' /t &quot;%1&quot; &quot;%2&quot; &quot;%3&quot; &quot;%4&quot;',
                               fileName,
                               &quot;TOSHIBA B-SA4TP TS&quot;,
                               printJobSettings.printerDriverName(),
                               printJobSettings.printerPortName());

            winAPI::shellExecute(adobeExe,  adobeParm);

            WeightInReal = sleep(500);

            prodJournalProdLoc = ProdJournalProd_ds.getNext();
         }
     CodeAccessPermission::revertAssert();
    }
    catch(Exception::CLRError)
    {
        errorMessage = AifUtil::getClrErrorMessage();

        CodeAccessPermission::revertAssert();

        throw error(errorMessage);
    }
    //END
}

Weight Detection PortComm

//Get PortComm number that already set from .txt file on local drive.
private str getPortComm()
{
    #file
    str getCOMport;
    boolean cekPortExist;
    AsciiIo file;
    Container data;
    int i;
    System.IO.FileInfo fileInfo;
    ;

    new InteropPermission(InteropKind::ClrInterop).assert();
    fileInfo = new System.IO.FileInfo(@”C:\portcomm.txt”);
    if(fileInfo.get_Exists())
    {
        file = new AsciiIo(@”C:\portcomm.txt”,#io_read);
        file.inFieldDelimiter(‘\t’);
        file.inRecordDelimiter(‘\n’);

        if(file)
        {
            while(file.status() == IO_Status::Ok)
            {  
                data = file.read();
                for(i = 1; i <= conlen(data); i++)
                {
                    getCOMport = any2str(conpeek(data, i));
                }
            }
        }

    }

    return strLTrim(getCOMport);
}

————————————

//Get Weight from PortComm
private real AI_getWeight()
{
    System.String netstring;
    System.String sample;

    int WeightInReal;
    int tryCount;
    str value;
    str value2;
    str portComm;
    System.IO.Ports.SerialPort port3;
    real weightFinal;

    tryCount = 0;

    portComm = this.getPortComm();
    if(portComm)
    {
        port3 = new System.IO.Ports.SerialPort();
        value = “0”;
        port3.set_PortName(portComm);
        port3.set_BaudRate(9600);
        port3.set_Parity(System.IO.Ports.Parity::None);
        port3.set_DataBits(8);
        port3.set_StopBits(System.IO.Ports.StopBits::One);
        port3.set_Handshake(System.IO.Ports.Handshake::None);

        try
        {
            port3.Open();
            while(tryCount<1)
            {
                WeightInReal = sleep(500);
                netstring = port3.ReadExisting();
                value = netstring;
                value2 = value;
                tryCount++;
            }
            port3.Close();
            port3.Dispose();
        }
        catch(Exception::CLRError)
        {
            info(“Wrong Port Comm Number”);
        }

        value2 = strReplace(value,”=”,””);
        value2 = strReplace(value2,”-“,””);
        value2 = strLTrim(value2);
        value2 = subStr(value2,1,6);
        weightFinal = str2num(value2);
    }
    else
    {
        info(“Check file portcomm.txt at C:\””);
    }

    if(!weightFinal)
    {
        info(“Please check your device, clarify it already turned on”);
    }
    return weightFinal;
}

—————————

on method button clicked, override.. some example here for you

void clicked()
{
    real _value;
    InventTable inventTableLoc;
    super();
    _value = this.AI_getWeight();
    
    Select * from inventTableLoc where inventTableLoc.ItemId == ProdJournalProd.ItemId;
    if(_value)
    {
        if(inventTableLoc.AISatuanPrimer!=”Kg”)
        {
            ProdJournalProd.AISatuanTertier = _value;
            ProdJournalProd_AISatuanTertier.enabled(False);
        }
        else
        {
            ProdJournalProd.AISatuanTertier =_value;
            ProdJournalProd_AISatuanTertier.enabled(True);
        }
    }
    ProdJournalProd_ds.executeQuery();
}

Location and Pallet Id Validation before posting form: ProdJournalTransBOM

void clicked()
{
    WMSPallet wmsPallet;

    select wmsPallet where wmsPallet.wMSPalletId==InventDimGrid_wMSPalletId.valueStr();
    if(wmsPallet.wMSLocationId != InventDimGrid_wMSLocationId.valueStr())
    {
        warning(strFmt(“Number of pallet %1 does not match in number of location %2″,InventDimGrid_wMSPalletId.valueStr(),InventDimGrid_wMSLocationId.valueStr()));
        error(“Posting has been canceled”);
    }
    else
    {
        super();
    }
}