30 Ocak 2019 Çarşamba

AX - 2012 Send Purchase order report as email

Send Purchase order report (PurchPurchaseOrder) as mail:

    SrsReportRunController          controller = new SrsReportRunController();
    PurchPurchaseOrderContract      Contract = new PurchPurchaseOrderContract();
    SRSPrintDestinationSettings     printSettings;
    VendPurchOrderJour              orderJour;
    SrsReportEMailDataContract      emailContract = new SrsReportEMailDataContract();

   select firstonly orderJour
            order by PurchOrderDate Desc,CreatedDateTime Desc
            where orderJour.PurchId == "ST000181";

    emailContract.parmAttachmentFileFormat(SRSReportFileFormat::PDF);
    emailContract.parmSubject("Purchase Order");
    emailContract.parmTo("test@hotmail.com");
    
    
    controller.parmReportName(ssrsReportStr(PurchPurchaseOrder, Report));
    controller.parmShowDialog(false);
    Contract.parmRecordId(orderJour.RecId);
    controller.parmReportContract().parmRdpContract(Contract);

    printSettings = controller.parmReportContract().parmPrintSettings();
    printSettings.printMediumType(SRSPrintMediumType::Email);
    printSettings.fileFormat(SRSReportFileFormat::PDF);
    printSettings.parmEMailContract(emailContract);
    printSettings.overwriteFile(true);

    controller.runReport();

There is a disadvantage of method at upper; AX will use Outlook for send email. Alternate is below has another disadvantage; it will generate a .PDF file at disk.:


  PurchTable          purchTable;
    str                 body;
    PurchLine           purchLine;
    boolean             found;
    VendPurchOrderJour  orderJour;
    Filename            filename;
    SysMailer           mailer;
    SysEmailParameters  parameters;
      SrsReportRunController  controller = new SrsReportRunController();
    PurchPurchaseOrderContract  contract = new PurchPurchaseOrderContract();
SRSPrintDestinationSettings printSettings;    
    
    controller.parmReportName(ssrsReportStr(PurchPurchaseOrder,Report));
    controller.parmExecutionMode(SysOperationExecutionMode::Synchronous);
printSettings = controller.parmReportContract().parmPrintSettings();
printSettings.fileFormat(SRSReportFileFormat::PDF);
printSettings.printMediumType(SRSPrintMediumType::File);
printSettings.overwriteFile(true);


printSettings.fileName(@filename);
    filename = strFmt(@"%1%2.PDF",WinAPI::getTempPath(),"PO00001");

     select firstonly orderJour
            order by PurchOrderDate Desc,CreatedDateTime Desc
            where orderJour.PurchId == "PO00001"
    contract.parmRecordId(orderJour.RecId);
    controller.parmReportContract().parmRdpContract(contract);
    
    controller.parmShowDialog(false);
    controller.runReport();
    infolog.clear();
    
    new InteropPermission(InteropKind::ComInterop).assert();
    mailer = new SysMailer();
    parameters = SysEmailParameters::find();


    if (parameters.SMTPRelayServerName)
    {
        mailer.SMTPRelayServer(parameters.SMTPRelayServerName,
                            parameters.SMTPPortNumber,
                            parameters.SMTPUserName,
                            SysEmailParameters::password(),
                            parameters.NTLM);
    }
    else
    {
        mailer.SMTPRelayServer(parameters.SMTPServerIPAddress,
                            parameters.SMTPPortNumber,
                            parameters.SMTPUserName,
                            SysEmailParameters::password(),
                            parameters.NTLM);
    }
       
    body = strFmt(@"<br><caption>%1</caption><br><br>","Purchase order form is appended.");      
    
    mailer.fromAddress("sender@hotmail.com");
    mailer.tos().appendAddress("test@hotmail.com");
    mailer.htmlBody(body);
    mailer.subject(title);
    mailer.attachments().add(filename);
   
    mailer.sendMail();

24 Ocak 2019 Perşembe

AX 2012 - Exchange rate edit, calculate, convert currency amount to default amount

Find exchange rate:

ExchangeRateCurrencyPair    pair;

//TCMB : Exchange rate type (ExchangeRateType) tablle Name key field
select firstOnly pair
                    where pair.ExchangeRateType == ExchangeRateType::findByName("TCMB").RecId &&
                        pair.FromCurrencyCode == "USD" &&
                        pair.ToCurrencyCode == Ledger::accountingCurrency(CompanyInfo::current());


this.ExchangeRate = ExchangeRate::findByDate(pair.RecId,systemDateGet()).ExchangeRate;

Edit method for exchange rate entry ( There're a lot of samples at default forms like SalesTable ) :

public edit CurrencyExchangeRate editExchRate(boolean set, CurrencyExchangeRate _exchRate)
{
    ExchangeRateHelper exchangeRateHelper = ExchangeRateHelper::newCurrency(Ledger::primaryLedger(CompanyInfo::findDataArea(curext()).RecId), this.Currency);

    if (set)
    {
        this.ExchangeRate = exchangeRateHelper.prepareExchangeRateForStorage(_exchRate);
    }
    else
    {
        _exchRate = exchangeRateHelper.displayStoredExchangeRate(this.ExchangeRate);
    }

    return _exchRate;
}

Calculate default currency amount from exchange rate:
ExchangeRateHelper exchangeRateHelper = ExchangeRateHelper::newCurrency(Ledger::primaryLedger(CompanyInfo::findDataArea(curext()).RecId), Ledger::accountingCurrency(CompanyInfo::current()));
 CurrencyExchangeHelper  cur = CurrencyExchangeHelper::construct();
   
cur.parmLedgerRecId(Ledger::primaryLedger(CompanyInfo::current()));
cur.parmExchangeDate(today());
//If you want to find daily currency rate from system, delete next two lines 
 cur.parmExchangeRate1(exchangeRateHelper.prepareExchangeRateForStorage(1));
cur.parmExchangeRate2(this.ExchangeRate);
    this.BudgetAmountMST = cur.calculateTransactionToAccounting(this.Currency,this.BudgetAmount,true);

or short type of upper:

info(strFmt("%1", Currency::curAmount(100,"usd",today(),UnknownNoYes::Yes,500,100)));

    info(strFmt("%1", Currency::curAmount2CurAmount(100,"usd","try",today())));

18 Ocak 2019 Cuma

AX 2012 - Change backcolor for Test/Dev/per company

Yo can write something like this to Run method of SysSetupFormRun class:

 this.design().colorScheme(FormColorScheme::RGB);
 this.design().backgroundColor(WinAPI::RGB2int(71,216,86));


or you can write a switch/case with curext() function.

12 Aralık 2018 Çarşamba

AX 2012 - Last cost price

You can put method to InventTable or any table which has ItemId field:

public CostPrice SNBfindLastPrice(DatePhysical _date = systemDateGet(),InventDim _inventdim = null)
{

    InventTrans           inventTrans;

    InventTransOrigin     origin;
    InventDim             inventdim;
    LineAmount            purchprice;
    RecId                 OK = false;
    InventDimParm         dimParm;
    InventDim             dimJoin;


    dimparm.initFromInventDim(_inventdim);


    select firstOnly CostAmountAdjustment,CostAmountPosted,Qty from inventTrans

                order by inventTrans.DateClosed desc,inventTrans.DateFinancial desc
            where inventTrans.ItemId == this.ItemId &&
                  !inventTrans.ReturnInventTransOrigin &&
                 inventTrans.DateClosed != dateNull() &&
                 inventTrans.DateClosed <= _date
        exists join origin
            where origin.RecId == inventTrans.InventTransOrigin &&
                  origin.ReferenceCategory == InventTransType::SummedUp
        #InventDimExistsJoin(inventTrans.InventDimId,dimJoin,_inventdim,dimParm);
    OK = inventTrans.RecId;

    if (!OK)

    {
        select firstOnly CostAmountAdjustment,CostAmountPosted,Qty from inventTrans
                    order by inventTrans.DateFinancial desc
                where inventTrans.ItemId == this.ItemId &&
                      !inventTrans.ReturnInventTransOrigin &&
                      inventTrans.Qty > 0 &&
                      inventTrans.DateFinancial <= _date
            exists join origin
                where origin.RecId == inventTrans.InventTransOrigin &&
                      origin.ReferenceCategory == InventTransType::Purch
            #InventDimExistsJoin(inventTrans.InventDimId,dimJoin,_inventdim,dimParm);
        OK = inventTrans.RecId;
    }
    if (!OK)
    {
        select firstOnly CostAmountAdjustment,CostAmountPosted,Qty from inventTrans
                    order by inventTrans.DateFinancial desc
                where inventTrans.ItemId == this.ItemId &&
                      inventTrans.Qty > 0 &&
                      inventTrans.DateFinancial <= _date
            exists join origin
                where origin.RecId == inventTrans.InventTransOrigin &&
                      origin.ReferenceCategory == InventTransType::SummedUp
            #InventDimExistsJoin(inventTrans.InventDimId,dimJoin,_inventdim,dimParm);
        OK = inventTrans.RecId;
    }
    if (!OK)
    {
        select firstOnly CostAmountAdjustment,CostAmountPosted,Qty from inventTrans
                    order by inventTrans.DateFinancial desc
                where inventTrans.ItemId == this.ItemId &&
                      inventTrans.Qty > 0 &&
                      inventTrans.DateFinancial <= _date
            exists join origin
                where origin.RecId == inventTrans.InventTransOrigin &&
                      ( origin.ReferenceCategory == InventTransType::InventTransaction ||
                        origin.ReferenceCategory == InventTransType::BOMMain)
            #InventDimExistsJoin(inventTrans.InventDimId,dimJoin,_inventdim,dimParm);
    }
    if (inventTrans.Qty != 0)
        return  abs( (inventTrans.CostAmountAdjustment+inventTrans.CostAmountPosted ) / inventTrans.Qty );
    else
        return 0;
}

15 Kasım 2017 Çarşamba

AX 2012 - Multiselect Lookup

There is a class and a sample form (tutorial_LookupMultiSelectGrid) at AOT for generate multi select lookup:

public class FormRun extends ObjectRun
{
    SysLookupMultiSelectCtrl msCtrl;
}


public void init()
{
   ...  
    super();
    ...
    
    msCtrl = SysLookupMultiSelectCtrl::construct(element, InventLocationIdExc, queryStr(InventLocationSRS));
    msCtrl.set(this.InventLocationList());
    ...
}

We can get list like below and set like up in init.

container InventLocationList()
{
    Container           Ids,Names;
    InventLocation      location;
    int i;
    RecId               recId;

    for (i=1;i<=conLen(vInventLocationIdExc);i++)
    {
        recId = conPeek(vInventLocationIdExc,i);
        select firstOnly location
            where location.RecId == recId;
        Ids += location.RecId;
        Names += location.InventLocationId;
    }

    return [Ids,Names];
}

We can save like this at Pack method:

container pack()
{
    ...
    vInventLocationIdExc    = msCtrl.get();
    ...
}

While MsCtrl.get() gives us RecId values below gives us field values:

container               c = msCtrl.getSelectedFieldValues();

14 Kasım 2017 Salı

AX 2012 - Add InventDim to Form Grid

Add InventDim table to data source, than make InnerJoin with table which inventDimId field used (in this sample table name is SNBProductDemonte).

Add a Group control like this at the grid:




Add this code to form:

public class FormRun extends ObjectRun
{
    InventDimCtrl_Frm_EditDimensions        inventDimFormSetup;
}
public void init()
{
    super();
    ...
    element.updateDesign(InventDimFormDesignUpdate::Init);
...

}

Object inventDimSetupObject()
{
    return inventDimFormSetup;
}

void updateDesign(InventDimFormDesignUpdate mode)
{
   InventDimParm inventDimParmVisible;

    switch (mode)
    {
        // Form Init
        case InventDimFormDesignUpdate::Init    :
            if (!inventDimFormSetup)
                inventDimFormSetup  = InventDimCtrl_Frm_EditDimensions::newFromForm(element);
                inventDimFormSetup.parmSkipOnHandLookUp( true);

                // Use the methods on InventDimParm
                // to set which dimensions to show when form is initialized
         //       inventdimparmvisible.inventsiteidflag       = true;
           //     inventdimparmvisible.InventLocationIdFlag   = true;
                inventDimFormSetup.parmDimParmVisibleGrid(inventDimParmVisible);

        // Datasource Active
        case InventDimFormDesignUpdate::Active  :
            inventDimFormSetup.formActiveSetup(InventDimGroupSetup::newItemId(SNBProductDemonte.ItemId)); 
            inventDimFormSetup.formSetControls( true);
            break;

        // Datasource Field change
        case InventDimFormDesignUpdate::FieldChange :
            inventDimFormSetup.formActiveSetup(InventDimGroupSetup::newItemId(SNBProductDemonte.ItemId)); 
            InventDim.clearNotSelectedDim(inventDimFormSetup.parmDimParmEnabled()); // InventDim is referring to datasource name
            inventDimFormSetup.formSetControls( true);
            break;

        default :
            throw error(strFmt ("@SYS54195", funcName()));
    }
}

Add this code to table which InventDimId field:

public boolean validateWrite()
{
    boolean ret;

    SNBProductDemonte.InventDimId = InventDim::findOrCreate(InventDim).InventDimId;
    ret = super();
  
    return ret;
}

public int active()
{
    int ret;
    ret = super();

    element.updateDesign(InventDimFormDesignUpdate::Active);
    return ret;
}

Add this code to modified method of ItemId field:

public void modified()
{
    super();

    element.updateDesign(InventDimFormDesignUpdate::FieldChange);
    InventDim.clearNotSelectedDim(element.inventDimSetupObject().parmDimParmEnabled());
}


Add InventDimParmFixed Display menu item from AOT to form.

Source:
https://daxbeginners.wordpress.com/2014/08/05/how-to-dynamically-display-inventory-dimension/

Axapta - Don't Miss One Second When filtering Between Two DateTime Fields

If we take time 00:00 of day after last day and use < instead of <= we don't miss even one second:

fromDate = DateTimeUtil::newDateTime(FromDateEdit.dateValue(),0,DateTimeUtil::getCompanyTimeZone());
    toDate   = DateTimeUtil::newDateTime(ToDateEdit.dateValue()+1,0,DateTimeUtil::getCompanyTimeZone());

    while select count(RecId) from serviceOrderTable
                where serviceOrderTable.createdDateTime >= fromDate
                    && serviceOrderTable.createdDateTime < toDate