mercoledì 29 gennaio 2014

HOWTO: Caching display methods

Dynamics AX 2009 :

Add this line code in the FORM method init

Public void init()
{
     super();
     this.cacheAddMethod(tablemethodstr(<table>,<display method>), [_updateOnWrite]);  
}

Dynamics AX 2012:

Add this line code in the DISPLAY method before the declaration

[SysClientCacheDataMethodAttribute([_updateOnWrite])]
Display method calcLeagueWon(int _num)
{
     If(juv || haveBoat())
          _num += 2

Return _num;
}

venerdì 24 gennaio 2014

HOWTO: Create counting journal

InventDim inventDim;
InventJournalTrans journalTrans;
TmpImportInventJournal tableBuffer;
InventJournalTable inventJournal;
real lineNum = 1;
TmpImportInventJournal tmpTable; // tmpTable here is used to stored item counting data
InventJournalName inventJournalName;
NumberSeq numberSeq;
;
ttsbegin;
select forupdate * from inventJournal
where inventJournal.JournalId == inventJournalId;
select firstonly inventJournalName
where inventJournalName.JournalNameId == InventParameters::find().CountJournalNameId;
numberSeq = NumberSeq::newGetVoucherFromCode(inventJournalName.VoucherSeqId);
while select * from tmpTable
{
inventDim.clear();
journalTrans.clear();
inventDim.initValue();
inventDim.configId = tmpTable.configId;
inventDim.inventBatchId = tmpTable.inventBatchId;
inventDim.InventLocationId = tmpTable.InventLocationId;
inventDim.inventSerialId = tmpTable.inventSerialId;
inventDim.InventSiteId = tmpTable.InventSiteId;
inventDim.wMSLocationId = tmpTable.wMSLocationId;
inventDim = InventDim::findOrCreate(inventDim);
journalTrans.Voucher = numberSeq.voucher();
journalTrans.initValue();
journalTrans.initFromInventJournalTable(inventJournal);
journalTrans.LineNum = lineNum;
journalTrans.JournalType = inventJournal.JournalType;
journalTrans.TransDate = tmpTable.TransDate;
journalTrans.ItemId = tmpTable.ItemId;
journalTrans.initFromInventTable(InventTable::find(tmpTable.ItemId));
journalTrans.Counted = tmpTable.Counted;
Try replacing the statement journalTrans.Counted = tmpTable.Counted with:
//
journalTrans.Counted = tmpTable.Counted;
journalTrans.InventOnHand = InventSumDatePhysicalDim::onHandQty(countDate, itemId, inventDim,tmpInventDimParm);
//
journalTrans.InventDimId = inventDim.inventDimId;
if (journalTrans.validateWrite())
{
JournalTrans.insert(NoYes::Yes);
JournalTrans.inventMovement().journalSetCounted();
JournalTrans.update();
}
//
lineNum ++;
}
inventJournal.NumOfLines = lineNum -1;
inventJournal.update();
tmpTable.clear();
delete_from tmpTable;
ttscommit;

lunedì 13 gennaio 2014

HOWTO: Recalculate InventSum

InventSumRecalcItem InventSumRecalcItem;

InventSumRecalcItem = new InventSumRecalcItem("ITEM001", true);
InventSumRecalcItem.updatenow();

TIP: Closed and closedQty in inventsum table

The closedQty flag informs that all quantities for given inventory item and inventory dimension set to zero. No item in stock, no item in process of receiving/shipping, also item is not expected to be sold/purchased/produced. The closed flag informs that the monetary balance for given item and inventory dimension is zero. Basically it means that all the costs related to given item was written-of from inventory account to COGS/WIP etc. Usually, the closed flag is set by inventory closing.
(But in simple cases it can be set immediately during posting of inventory issue). 

HOWTO: The enumerator does not designate a valid element

When your code run on CIL remember to set to null any enumerator of Sets or Maps before made a change on it. If the enumerator is not restored to null a remove operation to a Map throw the error: The enumerator does not designate a valid element.

sabato 11 gennaio 2014

HOWTO: Finding User Sessions from SPID in Dynamics AX 2012

In previous versions of Dynamics AX, the “Online Users” form contained a column for SPID for each client sessions. This column was a useful tool in debugging blocked SPID. More specifically, it was used to find a user session that corresponded to a specific SPID as indicated in this blog post. In Microsoft Dynamics AX 2012 the SPID column is no longer available on the “Online Users” form. This post will describe how to find the user session corresponding to a particular SPID.
In Dynamics AX 2012, information about the user sessions can be directly included in the SQL connection context. Adding  this information has a small performance overhead. Therefore, it is not turned on by default. To include user session information in the connection context perform the following steps:


  1. Navigate to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Dynamics Server\6.0\01\Original (installed configuration). The last key, Original (installed configuration), is the key name for the current server configuration. If your system uses a different configuration that the original installed configuration, navigate to the currently active configuration.
  1. Create a string registry value called ‘connectioncontext’ and set the value to 1.
  1. Restart the AOS.


Next open SQL Server Management Studio and run the following query to look at all the sessions related to Microsoft Dynamics AX:
select cast(context_info as varchar(128)) as ci,* from sys.dm_exec_sessions where program_name like '%Dynamics%'
Here’s the sample output. Let’s take a closer look at the ci column.
image
The first two items in the connection information are AX user id and the AX session id. So for SQL session_id 60 the user is ‘Admin’ and AX session id is 3. Next we can open the “Online Users” form to find the user session associated with the SPID.
image

venerdì 3 gennaio 2014

SQL: Taking the result from a dynamics sp_executesql query

DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);
DECLARE @CountSQLQuery varchar(30);

SET @SQLString = N'SELECT @result = COUNT(*) FROM INFORMATION_SCHEMA.TABLES';
SET @ParmDefinition = N'@result varchar(30) OUTPUT';

EXECUTE sp_executesql @SQLString, @ParmDefinition, @result=@CountSQLQuery OUTPUT;
SELECT CAST(@CountSQLQuery as int);

SQL: Retrive a new RECID for insert direct on Dynamics Ax table

DECLARE @TABLENAME nvarchar(40)
DECLARE @TABLEID int

SET @TABLENAME = 'TABLENAME'

IF (@TABLENAME = '')
BEGIN
RAISERROR ('Il parametro @TABLENAME deve essere specificato', 16, 1);
RETURN
END

SELECT @TABLEID = TABLEID FROM SQLDICTIONARY WHERE NAME = @TABLENAME AND FIELDID = 0
IF (ISNULL(@TABLEID, 0) = 0)
BEGIN
RAISERROR ('The table %1.40s does not exists', 16, 1, @TABLENAME);
RETURN
END

BEGIN TRANSACTION
DECLARE @RECID bigint = (SELECT NEXTVAL FROM SYSTEMSEQUENCES WHERE TABID = @TABLEID AND NAME = 'SEQNO')
IF (ISNULL(@RECID, 0) = 0)
BEGIN
RAISERROR ('Unable to get new RECID for the table  %1.40s', 16, 1, @TABLENAME);
RETURN
END

UPDATE SYSTEMSEQUENCES SET NEXTVAL = @RECID + 1 WHERE TABID = @TABLEID AND NAME = 'SEQNO'
COMMIT TRANSACTION


SELECT @RECID

TIP: Using of SysObsoleteAttribute

[SysObsoleteAttribute('Use method Args::create() instead', true)]
public static Args create(container _pack)
{
    Args sysArgs = new Args();
    sysArgs.unpack(_pack);
    return sysArgs;
}

HOWTO: Find reference for product variant for the current product master

// which has following product dimensions:
// configuration – 001
// size – XL
// color - Red

EcoResDistinctProductVariantRecId productVariantRecId;
container productDimensions = EcoResProductVariantDimValue::getDimensionValuesContainer(„001‟, „XL‟, „Red‟);

// find product variant surrogate key for product master and specified product dimensions

productVariantRecId = EcoResProductVariantExistMgr::findVariantByMasterAndDimensions(productMaster.RecId, productDimensions));

HOWTO: Find product master record by product number

EcoResProductMaster productMaster;
// find product master buffer by providing product number

productMaster = EcoResProduct::findByProductNumber("MyProductMAster");

HOWTO: Determine whether a dimension for a specific field is active

InventTable inventTable;
InventDimGroupSetup inventDimGroupSetup;
InventDimGroupFieldSetup inventDimGroupFieldSetup;
inventDimGroupSetup = InventDimGroupSetup::newInventTable(inventTable);
inventDimGroupFieldSetup = inventDimGroupSetup.getFieldSetup(fieldNum(InventDim,WMSPalletId));
if (inventDimGroupFieldSetup.isActive())
{
     info(strFmt("The palletId dimension is active for dimension group   %1",inventDimGroupSetup.getStorageDimensionGroup()));));
}

HOWTO: MultiSelectionHelper

MultiSelectionHelper helper;
;
helper = MultiSelectionHelper::construct();
helper.parmDatasource(_formDataSource);
record = helper.getFirst();
while (transFilm.RecId != 0)
{
   /*Do something*/
   record = helper.getNext();
}

HOWTO: Save and Restore InfoLog

InfologData infologData;
void saveInfolog()
    {
        ;
        // here we report something
        error("something awful");
        error("something terrible");
        setprefix("scary");
        warning("mouse");
// here we get infolog data
        infologData = infolog.infologData();
infolog.clear(0);
    }
void restoreInfolog()
    {
        ;
        // here we view infolog once again
        infolog.import(infologData);
    }
    ;
saveInfolog();
restoreInfolog();
infolog.view(x.InfoLogData);
info(Info::infoCon2str(x.InfoLogData));

AX 2012: The request was aborted: Could not create SSL/TLS secure channel

The error you're encountering, "The request was aborted: Could not create SSL/TLS secure channel," can occur due to various re...