Senin, 29 Juni 2020

Lookup based on Fromdate Todate

public void lookup()
{
   
    Query                       query = new Query();
    QueryBuildDataSource        queryBuildDataSource;
    QueryBuildRange             queryBuildRange;
    SysTableLookup              sysTableLookup = SysTableLookup::newParameters(tableNum(CustPaymFee), This);
    ;
    //2daydate  = today();
    sysTableLookup.addLookupField(fieldNum(CustPaymFee, FeeId));
    sysTableLookup.addLookupField(fieldNum(CustPaymFee, Description));
    sysTableLookup.addLookupField(fieldNum(CustPaymFee, LedgerJournalType));
   
    queryBuildDataSource = query.addDataSource(tableNum(CustPaymFee));
    queryBuildDataSource.addRange(fieldNum(CustPaymFee, PSMFromdate)).value("<"+SysQuery::value(today()));
    //queryBuildRange.value('<='+SysQuery::value(today())); <= its not working
    queryBuildDataSource.addRange(fieldNum(CustPaymFee, PSMtodate)).value(">"+SysQuery::value(today()));
    //queryBuildRange.value('>='+SysQuery::value(today())); >= its not working
   
    sysTableLookup.parmQuery(query);
    // Perform lookup
    sysTableLookup.performFormLookup();
   
}

Senin, 22 Juni 2020

How to get last Approval

static void dtGetLastApproverName(Args _args) 
 { 
    WorkflowTrackingStatusTable workflowTrackingStatus; 
    WorkflowTrackingTable workflowTrackingTable; 
    WorkflowTrackingCommentTable workflowTrackingCommentTable; 
    UserInfo userInfo; 

    select firstFast RecId, User from workflowTrackingTable 
     order by RecId desc 
     join workflowTrackingCommentTable 
    where workflowTrackingCommentTable.WorkflowTrackingTable == 
          workflowTrackingTable.RecId 
    join UserInfo where UserInfo.id == WorkflowTrackingTable.User 
    exists join workflowTrackingStatus 
    where workflowTrackingTable.WorkflowTrackingStatusTable == 
    workflowTrackingStatus.RecId 
    && workflowTrackingStatus.ContextRecId == _salesRecId //PurchRecID 
    && workflowTrackingStatus.ContextTableId == tableNum(SalesTable) //SalesTable 
    && workflowTrackingTable.TrackingType == WorkflowTrackingType::Approval; 

    if (workflowTrackingTable.RecId > 0) 
    { 
      info(strFmt(“%1 – %2 “,userInfo.name, workflowTrackingCommentTable.RecId)); 
    } 
 } 

You can get this code from : https://allaboutax.blogspot.com/2018/06/retrieve-last-approver-name-for-workflow.html?showComment=1592880782308#c5936258997657022271


Rabu, 27 Mei 2020

Error http://tempuri.org

when you got an error in AX and you start looking forward for solution in the internet you will found the same way how to "cure" the illness.
going to AOS Service > restart the service. or Redeploy the BIService.
and sometimes those solutions is not working at all. 
the error "The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:queryBuilderArgs..bla..bla..bla.." we found that its because the BIService failed but its caused your drive where the SQL Server SSRS installed is getting full. its not have enough space to process all the request.

Rabu, 29 April 2020

System does not support setup 'continuous' of number sequence

When we work with entries data that contain sequence number sometime we need an improvement to create in another way, a Generate perhaps.

Usually we can use the code like this :

//number sequence MRIS
    NumberSeq                       num;
;

num = NumberSeq::newGetNum(InventParameters::[method for Sequence number]);

it can be work if the continuous cekbox, in Sequence number master is false.

but fi the continuous cekbox, in Sequence number master is True, the system will give a message "System does not support setup 'continuous' of number sequence"

so you need to put ttsbegin and ttscommit on your codes :

NumberSeq                       num;
Sampletable                      sampletable;
;
ttsbegin;

num = NumberSeq::newGetNum(InventParameters::[method for Sequence number]);
sampletable.clear();
sampletable.number =  num.num();
sampletable.insert();

ttscommit;

  

Selasa, 07 April 2020

Show Active bank account

In Ax2012 there is VendBankAccount table.
there's one field shown on our screen that gives us information the state of bank account. Active or inactive.
unfortunately this information made by a method.

so how to make a query to filter or specify the record, active or inactive?
Activedate and Expiredate in VendBankAccount, both made by UTCDateTime
Bank account state made by method.

i guess for some programmer it is gonna be tricky.

Working with UTCDateTime is need call another method dan extended data type especially to get current date and time.

this is my example method how to filter/specify whether the Bank Account is active or expired.
i applied this method when user Lookup Bank Account.

static void lookupVendBankAccountId(FormStringControl _formControl, VendAccount _vendAccount)
{
    SysTableLookup          sysTableLookup;
    Query                   query;
    QueryBuildDataSource    qbds;
    
    //Working with UTCDateTime
    date                    currentdate;
    TimeOfDay               currenttime;
    utcDateTime             rangedate;
    //macro for define Expire date condition
    #localmacro.ExpiryDateCriteria "((ExpiryDate == \%1) || (ExpiryDate > \%2))" #endmacro
    #localmacro.ActiveDateCriteria "(ActiveDate <= \%1)" #endmacro
    
    
    ;
    
    //Working With UTCDatetime
    currentdate = today();
    currenttime = timeNow();
    rangedate = DateTimeUtil::newDateTime(currentdate,currenttime,DateTimeUtil::getUserPreferredTimeZone());

    sysTableLookup = SysTableLookup::newParameters(tableNum(VendBankAccount), _formControl);

    query = new Query();
    qbds = query.addDataSource(tableNum(VendBankAccount));
    qbds.addRange(fieldNum(VendBankAccount, VendAccount)).value(SysQuery::value(_vendAccount));
    //specify the active or inactive bank account 
    qbds.addRange(fieldNum(VendBankAccount, ActiveDate)).value(strFmt(#ExpiryDateCriteria, date2StrXpp(dateNull()) , DateTimeUtil::toStr(rangedate)));
    
    
    
    sysTableLookup.addLookupfield(fieldNum(VendBankAccount, AccountId));
    sysTableLookup.addLookupfield(fieldNum(VendBankAccount, Name));
    sysTableLookup.addLookupfield(fieldNum(VendBankAccount, AccountNum));
    sysTableLookup.addLookupfield(fieldNum(VendBankAccount, ContactPerson));
    sysTableLookup.addLookupfield(fieldNum(VendBankAccount, VendAccount));

    sysTableLookup.parmQuery(query);
    sysTableLookup.performFormLookup();
}

  


  

Kamis, 05 Desember 2019

Custom notification

If you want to try custom your notification, 
AX Standard can bring the user to the form where the information exist but when the form was open system show all the records. try modify this class EventContextInformation to get just only selected record show front of your desk.

this custom method found by Rony.

Jumat, 01 November 2019

Create record Purchase Agreement through x++

My code here is to copy Purchase Agreement line from reference Purchase Agreement to new Purchase Agreement.

static void PSMCopydirecttoagreementline(Args _args)
{
    AgreementLineQuantityCommitment agreementLineQuantity;
    AgreementLineQuantityCommitment xagreementLineQuantity;
    AgreementLineVolumeCommitment   agreementlinevolume;
    AgreementLineVolumeCommitment   xagreementlinevolume;
    PurchAgreementHeader            purchAgreementHeader = PurchAgreementHeader::findAgreementId("PSM-000020");//Header reference
    purchAgreementHeader            xpurchagreementheader =  PurchAgreementHeader::findAgreementId("PSM-000078");//Header baru



    //Jika Komitment Purchase Agreement berdasaran kuantity
    if(purchAgreementHeader.DefaultAgreementLineType == CommitmentType::ProductQuantity)
    {
        info("Quantity based");
        //copy line AgrementLIneQuanity menjadi line baru
        while select agreementLineQuantity
            where agreementLineQuantity.Agreement == purchAgreementHeader.RecId
        {
            xagreementLineQuantity.clear();
            xagreementLineQuantity.data(agreementLineQuantity);
            xagreementLineQuantity.Agreement = xpurchagreementheader.RecId;
            xagreementLineQuantity.doInsert();
        }
    }
    else
    {
        //Jika Komitment Purchase Agreement BUKAN berdasaran kuantity
        info("value based");
        while select agreementlinevolume
            where agreementlinevolume.Agreement == purchAgreementHeader.RecId
        {

            xagreementlinevolume.clear();
            xagreementlinevolume.data(agreementlinevolume);
            xagreementlinevolume.Agreement = xpurchagreementheader.RecId;
            xagreementlinevolume.doInsert();
        }
    }

}

below is how to setup and create new Purchase Agreement(header) from reference Purchase Agreement(header) through x++

void createDuplicate()
{
    ttsBegin;
    this.setHeader();
    this.createPurchAgreementHeader();
    this.setLine();
    //this.createAgreementLine();
    ttsCommit;

    info("done");
}

void setHeader()
{
    PurchAgreementId    tmpAgreementId;
    NumberSeq           num;

    xpurchagreementheader.clear();
    xpurchagreementheader.data(purchAgreementHeader);
    xpurchagreementheader.WorkflowStatus_PSN = PurchAgreementWorkflowStatus::NotSubmitted;
    xpurchagreementheader.PSMTotalNetAmount = 0;


    num = NumberSeq::newGetNum(PurchParameters::numRefPurchAgreementId());
    tmpAgreementId = num.num();

    info(strFmt("num %1",tmpAgreementId));
    if (PurchAgreementHeader::findAgreementId(tmpAgreementId).RecId)
    {
        num.abort();
        checkFailed("@SYS19304");
        checkFailed(strfmt("@SYS24176", tmpAgreementId));
        throw error("@SYS23020");
    }

    xpurchagreementheader.PurchNumberSequence = tmpAgreementId;
    num.used();

    agreementHeaderDefault = AgreementHeaderDefault::findAgreementHeader(purchAgreementHeader.RecId);
    if(agreementHeaderDefault.RecId)
    {
    xgreementHeaderDefault.clear();
    xgreementHeaderDefault.data(agreementHeaderDefault);

    }
    purchAgreementHeaderDefault = PurchAgreementHeaderDefault::findPurchAgreementHeader(purchAgreementHeader.RecId);
    if(purchAgreementHeaderDefault.RecId)
    {
    xpurchAgreementHeaderDefault.clear();
    xpurchAgreementHeaderDefault.data(purchAgreementHeaderDefault);

    }

void createPurchAgreementHeader()
{
    xpurchagreementheader.insert();

    xgreementHeaderDefault.AgreementHeader = xpurchagreementheader.RecId;
    xgreementHeaderDefault.insert();

    xpurchAgreementHeaderDefault.PurchaseAgreementHeader = xpurchagreementheader.RecId;
    xpurchAgreementHeaderDefault.insert();
}

note :
u must define/create those 3 method createDuplicate(),setHeader() and createPurchAgreementheader() in the class. for me i called those three methods in run() method.




Cloud hosted environment di D365

Biasanya kita menginginkan sebuah environment yang sama dengan LIVE/PROD untuk mengtest sebuah proses. Maka kita bisa menggunakan fitur Clou...