Rabu, 28 Desember 2022

Disk Full pada saat meloading report (Environment RDP)


Berikut trouble solving untuk Environment AX melalui RDP.

https://community.dynamics.com/ax/b/fsilvajunior/posts/full-disk-remote-desktop-servers-issue

Kamis, 15 Desember 2022

Rabu, 19 Oktober 2022

Membuat Class yang memanggil multiple MenuItem

1. Buat Class , contoh Class Testcallmultiplemenuitem
2. di declarasi class tambahkan variable.
    
        Args            args;

3. Buat method yang mereturn/hasilkan value Args

public Args parmArgs(Args _args = args)
{
    args = _args;

    return args;
}

4. Buat main method 

static void main(Args       _args)
{
    Testcallmultiplemenuitem            testcall = New Testcallmultiplemenuitem();
    testcall.parmArgs(_args);
    testcall.run();
}

5. Buat Menuitem action contoh TestPost, TestGeneratejournal
dengan label TestPost = "Post", TestGeneratejournal = "generate"

6. Buat method Run()

public void Run()
{
    //bisa menambahkan vairable yang dibutuhkan contoh.
    Testupdateheaderconfirm         updateheaderconfirm ;

    switch(this.parmArgs().menuItemName())
    {
        case "TestPost":
        if(args.record())
        updateheaderconfirm = this.parmArgs().record();
        idrekapmris = updateheaderconfirm.RekapID;
        this.ValidateSMRIS(idrekapmris);//Method yang menjalankan proses
        break;

        case "generate":
        if(args.record())
        updateheaderconfirm = this.parmArgs().record();
        idrekapmris = updateheaderconfirm.RekapID;
        this.FindJournalAdjusment(idrekapmris);
        break;
       
    }

}





}



Jumat, 14 Oktober 2022

Error Posting Jurnal AP Transaction have been selected for settlement, although settlement type:none was selected for vendor [], voucher []

https://ax2012infolog.wordpress.com/2017/07/24/apjournalpayment-journal-it-unable-to-post-or-non-post-journal-have-a-message-appears-transactions-have-been-selected-for-settlement-although-settlement-type-none-was-selected-for-vendor/comment-page-1/?unapproved=13&moderation-hash=d8cd36e7fc52be482ded2c8773262ca8#comment-13

Kamis, 15 September 2022

Membuat custom workflow pada form

Kita akan ambil contoh menambahkan Workflow approval di pembuatan ItemId.

table yang akan kita gunakan adalah : EcoResProduct



1. Buat sebuah enum dengan lima opsi/element.
contoh Productreleaseapprovalstate.
Productreleaseapprovalstate.Draft
Productreleaseapprovalstate.Inreview
Productreleaseapprovalstate.Canceled
Productreleaseapprovalstate.Rejected
Productreleaseapprovalstate.Approved

2. Tambahkan enum tadi di table EcoResProduct

3. ditable EcoResProduct tambahkan method canSubmittoWorkflow
            public boolean canSubmitToWorkflow(str _workflowType = '')
{
    boolean ret = false;

    if(this.RecId && this.PSMReleaseproductstate == PSMReleaseproductstate::Draft)
        ret = true;
    //ret = super(_workflowType);
    

    return ret;
}

4. ditable EcoResProduct tambahkan method updateWorkflowState
static void updateWorkflowState(RefRecId        _Id, PSMReleaseproductstate     _state)
{
    EcoResProduct       ecoresproduct;
    ;
    
    ecoresproduct = EcoResProduct::find(_Id, true);
    ttsBegin;
        ecoresproduct.PSMReleaseproductstate = _state;
        ecoresproduct.update();
    ttsCommit;
}

5. Buat Query

6. Buat Workflow category
    Expand workflow category > Klik kanan > pilih New Workflow category.
    Properties :
                        key in nama category, label, help text, pilih modulenya.

7. Buat menu item display untuk formnya. jika sudah ada maka tidak usah.

8. Buat Workflow type
    Expand Workflow
    Pilih Workflow type > klik kanan > Add ins > Workflow type wizard.
    Nama : isi dengan nama Workflowtype
    Query : isi dengan query yang tadi dibuat
    Document menu item : isi dengan menu item diplay dari formnya.
    Workflow category : isi dengan WF Category yang tadi dibuat.

9. Edit Properties Workflow type.
    Label
    Help text

10. Edit properties menuitem Cancel dan Submit.
    Label
    Help text

11. Edit Properties form,
        Workflow enable = Yes
        Workflow datasource = [nama table]
        Workflow type = [isi dengan worklfow type yang tadi dibuat]

12. Expand class Submit Manager, buka Class declaration. tambahkan variable dibawah ini dan nama Table yang dipakai.
    InventTable                         inventTable;
    WorkflowVersionTable                workflowConfigurationTable;
    WorkflowComment                     workflowComment;
    boolean                             submit;
    WorkflowWorkItemTable               workflowWorkItemTable;
    UserId                              userId;
    MenuItemName                        menuItemName;
    EPWorkflowControlContext            workflowControlContext;
    WorkflowTypeName                    workflowTemplateName;

13. Buat method parmData
public InventTable   parmData(InventTable _currData = currData)
{
    ;

    currData = _currData;

    return currData;
}

14. Buat method parmMenuItem
public MenuItemName parmMenuItemName(MenuItemName _menuItemName = menuItemName)
{
    ;

    menuItemName = _menuItemName;

    return menuItemName;
}

15. Buat method parmSubmit
public boolean parmSubmit(boolean _submit = submit)
{
    ;

    submit = _submit;

    return submit;
}

16. Buat method parmWorkflowComment
public WorkflowComment parmWorkflowComment(WorkflowComment _workflowComment = workflowComment)
{
    ;

    workflowComment = _workflowComment;

    return workflowComment;
}

17 Buat method parmWorkflowConfigurationTable
public WorkflowVersionTable parmWorkflowConfigurationTable(WorkflowVersionTable _workflowConfigurationTable = workflowConfigurationTable)
{
    ;

    workflowConfigurationTable = _workflowConfigurationTable;

    return workflowConfigurationTable;
}

18. Buat method parmWorkflowControlContext
public EPWorkflowControlContext parmWorkflowControlContext(EPWorkflowControlContext _workflowControlContext = workflowControlContext)
{
    ;

    workflowControlContext = _workflowControlContext;

    return workflowControlContext;
}

19. Buat method parmWorkflowTemplateName
public WorkflowTypeName parmWorkflowTemplateName(WorkflowTypeName _workflowTemplateName = workflowTemplateName)
{
    ;

    workflowTemplateName = _workflowTemplateName;

    return workflowTemplateName;
}

20. Buat method parmWorkflowWorkItemtable
public WorkflowWorkItemTable parmWorkflowWorkItemtable(WorkflowWorkItemTable _workflowWorkItemTable = workflowWorkItemTable)
{
    ;

    workflowWorkItemTable = _workflowWorkItemTable;

    return workflowWorkItemTable;
}

21. Buat method
void reSubmit(Args _args, RecId _recId)
{
    InventTable         localData;
    NoYes                     reSubmittingFromWeb;
    ;

    update_recordset localData setting IsWorkflowToBeResubmitted = true
        where localData.RecId == _recId;

    Workflow::cancelWorkflow(this.parmWorkflowWorkItemtable().CorrelationId, this.parmWorkflowComment());
}

22. Buat method
public void submit()
{
    NoYes                       activatingFromWeb;
    InventTable                 inventtable;

    // If we have a workflow control context, we are being activated from EP
    activatingFromWeb = this.parmWorkflowControlContext() == null ? NoYes::No : NoYes::Yes;


    ttsbegin;

    InventTable::updateWorkflowState(currData.RecId, PSMRealaseProductWF::Inreview);
    Workflow::activateFromWorkflowType(this.parmWorkflowTemplateName(),
                                           currData.RecId,
                                           this.parmWorkflowComment(),
                                           activatingFromWeb,
                                           DirPersonUser::worker2UserId(currData.Preparer));


    ttscommit;
}

23. Buat MEthod
public static void main(Args args)
{
    InventTable                             localData;
    PSMReleasProducttypeSubmitManager       submitManager;
    boolean                                 ret = true;
    Object                                  callerDataSource;
    ;

    localData = args.record();

    submitManager = new PSMReleasProducttypeSubmitManager();
    submitManager.parmData(localData);

    if (args.menuItemName() == menuitemActionStr(PSMReleasProducttypeSubmitMenuItem) ||
        args.menuItemName() == menuitemActionStr(PSMReleasProductApprResubmitMenuItem))
    {
        submitManager.init(args.record(), args.menuItemName(), args.caller().getActiveWorkflowConfiguration(), args.caller().getActiveWorkflowWorkItem(), null);
    }
    else
    {
        submitManager.init(args.record(), args.menuItemName(), null, null, args.caller());
    }

    if (ret && submitManager.dialogOk())
    {
        if (args.menuItemName() == menuitemActionStr(PSMReleasProducttypeSubmitMenuItem))
        {
            submitManager.submit();
        }
        else
        {
            submitManager.reSubmit(args, localData.RecId);
        }
    }

    if (!webSession())
    {
        callerDataSource = args.record().dataSource();
        if (callerDataSource)
        {
            callerDataSource.research(true);
        }

        args.caller().updateWorkflowControls();
    }
}

24. Buat method
public boolean dialogOk()
{
    WorkflowSubmitDialog            workflowSubmitDialog;
    WorkflowWorkItemActionDialog    workflowWorkItemActionDialog;
    boolean                         ok;
    ;

    if (menuItemName == menuitemActionStr(PSMReleasProducttypeSubmitMenuItem))
    {
        workflowSubmitDialog = WorkflowSubmitDialog::construct(this.parmWorkflowConfigurationTable());
        workflowSubmitDialog.run();
        this.parmWorkflowComment(workflowSubmitDialog.parmWorkflowComment());
        ok = workflowSubmitDialog.parmIsClosedOK();
    }

    else if (menuItemName == menuitemActionStr(PSMReleasProductApprResubmitMenuItem))
    {
        workflowWorkItemActionDialog = WorkflowWorkItemActionDialog::construct( workflowWorkItemTable,
                                                                                WorkflowWorkItemActionType::Resubmit,
                                                                                new MenuFunction(menuitemActionStr(PSMReleasProductApprResubmitMenuItem), MenuItemType::Action));
        workflowWorkItemActionDialog.run();
        this.parmWorkflowComment(workflowWorkItemActionDialog.parmWorkflowComment());
        ok = workflowWorkItemActionDialog.parmIsClosedOK();
        userId = workflowWorkItemActionDialog.parmTargetUser();

    }

    return ok;
}

25. Buat method
public void init(   Common                      _documentRecord,
                    MenuItemName                _menuItemName,
                    WorkflowVersionTable        _workflowConfigurationTable,
                    WorkflowWorkItemTable       _workflowWorkItemTable,
                    EPWorkflowControlContext    _workflowControlContext
                    )
{
    //if (_documentRecord.TableId == tableNum(RsPcmSPLTable))
    //{
    //    this.parmData(_documentRecord);
    //}

    this.parmSubmit(_menuItemName == menuitemActionStr(PSMReleasProducttypeSubmitMenuItem));
    this.parmMenuItemName(_menuItemName);

    if (_workflowControlContext)
    {
        this.parmWorkflowControlContext(_workflowControlContext);
        this.parmWorkflowWorkItemtable(_workflowControlContext.getActiveWorkflowWorkItem());
        this.parmWorkflowComment(_workflowControlContext.getWorkflowComment());
        this.parmWorkflowTemplateName(_workflowControlContext.getActiveWorkflowConfiguration().workflowTable().TemplateName);
    }
    else
    {
        this.parmWorkflowConfigurationTable(_workflowConfigurationTable);
        this.parmWorkflowWorkItemtable(_workflowWorkItemTable);
        this.parmWorkflowTemplateName(this.parmWorkflowConfigurationTable().workflowTable().TemplateName);
    }
}






    

Jumat, 09 September 2022

RecordInsertList

https://docs.microsoft.com/en-us/previous-versions/dynamics/ax-2012/system-classes/gg923748(v=ax.60)?redirectedfrom=MSDN

Kamis, 18 Agustus 2022

LookupReference

Public Common lookupReference()
{
    Common                  ret;

    ret = HcmWorker::PSM_LookupReffWorker_ByDept(this,strFmt("%1",PSMPengajuantraining.Department), true);

    return ret;
}

Minggu, 14 Agustus 2022

Jumat, 05 Agustus 2022

Basic class dengan multi menuitem

Jadi disini akan digambarkan dan juga tutorial bagaimana membuat class yang bisa diakses oleh lebih dari satu menu item.
dimana menu item ini mempunyai masing-masing fungsi.

1. Buat class:
class PSMCMUpdatestate
{
    Args        args;
}

2. buat method constructor:
public static PSMCMUpdatestate construct()
{
    return new PSMCMUpdatestate();
}

3. buat method dengan return Args:
public Args parmArgs(Args _args = args)
{
    args = _args;

    return args;
}

4. buat method main:
method main memaggil method run
Public static void main(Args       _args)
{
    PSMCMUpdatestate    updatestate = PSMCMUpdatestate::construct();
    updatestate.parmArgs(_args);
    updatestate.run();    
    
}

5. buat method run:
method run mendefinisikan menuitem action yang masing2 menjalankan method berbeda atau bisa juga sama.
public void run()
{
    switch(this.parmArgs().menuItemName())
    {  
        case "MenuitemA":   
        if(Args.record())
           //defisinikan method yang akan dijalankan
        break;
        case "MenuitemB":   
        if(Args.record())
           //defisinikan method yang akan dijalankan
        break;
        case "MenuitemC":   
        if(Args.record())
           //defisinikan method yang akan dijalankan
        break;
    }
}

Kamis, 28 Juli 2022

Error Worfklow karena SSL/TLS AX2012

Stopped (error): ClrInterop Exception: Exception has been thrown by the target of an invocation.
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.

Solved by :
Restart ADFS di server.
ex : 10.23 dan 10.31
Restart AOT dimana server WF.
ex : 10.19

Done 

Kamis, 21 Juli 2022

Script untuk mengambil beberapa karakter dari satu buah Str parameter

static void PSMSplitstr2(Args _args)
{
    //mendapatkan '000002' dari str paramAsStr.

    str paramAsStr = "PSM22-000002";
    List paramAsList;
    ListEnumerator le;
    int             i = 0;
    str             getnumber;

    paramAsList = strSplit(paramAsStr, "-");
    
    le = paramAsList.getEnumerator();
    while(le.moveNext())
    {
        if(i==1)
        {
        getnumber = le.current();    
            info(getnumber);
        }
        i++;
    }
}

from
https://www.schweda.net/blog_ax.php?bid=628&wdl=en

Minggu, 26 Juni 2022

Searching deadlock in AX Database

Put this code to get know some process which caused some deadlock in AXDB

Select your AX Database and klik New Query :

SELECT  wt.session_id, 
    ot.task_state, 
    wt.wait_type, 
    wt.wait_duration_ms, 
    wt.blocking_session_id, 
    wt.resource_description, 
    es.[host_name], 
    es.[program_name] 
FROM  sys.dm_os_waiting_tasks  wt  
INNER  JOIN sys.dm_os_tasks ot ON ot.task_address = wt.waiting_task_address 
INNER JOIN sys.dm_exec_sessions es ON es.session_id = wt.session_id 
WHERE es.is_user_process =  1

Senin, 06 Juni 2022

Selasa, 29 Maret 2022

Class Product Receipt di AX2012

Jadi ditempat kerjaku sekarang ada requirement untuk menyimpan nomor kendaraan supplier yang mengantarkan barang.

Di standard AX tidak ada kolom no Polisi. jadi harus saya custom di PurchParmTable.
pertanyaanya class apa yang mengeksekusi Product receipt dan menciptakan record di VendPackingSlipJour.

Class yang mengekseskusinya ada di PurchPackingSlipJournalCreate.
Method yang saya pakai adalah PurchPackingSlipJournalCreate.initheader().

Class ini extends ke sebuah class abastract. Jadi jika ingin mendebug class ini kita harus menguncek CILL di User Option.

selamat mencoba

Jumat, 11 Februari 2022

Create notification x++

untuk menghardcode notification/lonceng di AX bisa memakai table-table berikut.

EventInbox  &   SysUserInfo 

Contoh penggunaan :

EventInbox                  EventInbox,inbox;
SysUserInfo                 SysUserInfo;


select SysUserInfo order by SysUserInfo.Id
       where SysUserInfo.Id == "Husna";//ax account Husna

        ttsbegin();
        select maxof(inboxId) from inbox;
        
        EventInbox.InboxId  = EventInbox::nextEventId();
        EventInbox.CompanyId = "psm";
        EventInbox.AlertTableId = 105939;//2271;//diisi dengan tableId yang menjadi referensi table.
        EventInbox.AlertCreatedDateTime = DateTimeUtil::utcNow();
        EventInbox.ParentTableId = 105939;//2271;//diisi dengan tableId yang menjadi referensi table.
        EventInbox.IsRead = NOYES::No;
        EventInbox.Subject = "Update minimum stock information "+usernotif.ItemId;
        EventInbox.AlertedFor = "update minimum stock information "+usernotif.ItemId;
        EventInbox.UserId = SysUserInfo.Id;
        EventInbox.ShowPopup = NOYES::Yes;
        EventInbox.Visible = NOYES::Yes;
        EventInbox.Message = strfmt("Minimum stok item "+usernotif.ItemId+" sudah lebih kecil atau sama dengan rata-rata pemakaian");
        EventInbox.insert();

        ttscommit();

Mencari userId dari HcmWorker.RecId

Untuk mencari User Id dari HcmWoker bisa menggunakan DirPersonUser::findParty()

contoh penggunaan :

HcmWorker            worker;
;

select worker
where worker.recId == 12345678;

info(DirPersonUser::findParty(worker.person).user);

Kamis, 10 Februari 2022

Highlight record with background color

Over write method displayOption di Datasource.

Contoh : 

public void displayOption(Common _record, FormRowDisplayOption _options)
{
    PSMLeadTimeItem         psmleadtimelocal;
    //super(_record, _options);
    psmleadtimelocal   =  _record as PSMLeadTimeItem;
    if(psmleadtimelocal.min == 0)
        _options.backColor(WinApi::RGB2int(255,255,0));//jadi kuning
    else
        _options.backColor(WinAPI::RGB2int(255,255,255));
}

Kamis, 27 Januari 2022

Error go to Origin

Tambahkan code berikut di Init form

if(this.args().menuItemName() != 'RS_HRIDN_BookingTransportPerm')
    {
        RS_HRIDN_BookingTransportPerm_ds.query().dataSourceTable(tableNum(RS_HRIDN_BookingTransportPerm))
        .addRange(fieldNum(RS_HRIDN_BookingTransportPerm, IsGatePermission)).value(SysQuery::value(NoYes::Yes));
    }

Kamis, 13 Januari 2022

Create Sequence number di AX2012

Contoh kasus :

Kita akan membuat form baru di modul Procurement and sourching. Kita bilang form ini form Berita Acara. 
form ini mempunyai datasource BeritaAcaratable. dengan fields :
  1. BeritaacaraId
  2. Transdate
  3. Description

  1. Buat Extended data type BeritaacaraId.
  2. Di Class NumberSeqModulePurchaseOrder/Loadmodule, tambahkan code berikut.
            //start husna 
            datatype.parmDatatypeId(extendedTypeNum(BeritaacaraId));
            datatype.parmReferenceHelp(literalStr("Berita acara"));
            datatype.parmWizardIsContinuous(true);
            datatype.parmWizardIsManual(NoYes::No);
            datatype.parmWizardIsChangeDownAllowed(NoYes::No);
            datatype.parmWizardIsChangeUpAllowed(NoYes::No);
            datatype.parmSortField(999999);

            datatype.addParameterType(NumberSeqParameterType::DataArea, true, false);
            this.create(datatype);
            //end husna
    3. Di table PurchParameter/Methods/ tambahkan methods berikut :
             //add Husna 20220113
            static client server NumberSequenceReference  numRefBeritaAcara()
            {
                    return NumberSeqReference::findReference(extendedTypeNum(BeritaacaraId));
            }

    4. Buat job untuk memanggil module tambahan dan Extended data yang dibuat tadi. Job seperti berikut :
        static void loadNumSeqPurchDemo(Args _args)
        {
            //define the class variable
            NumberSeqModulePurchaseOrder seqMod = new NumberSeqModulePurchaseOrder();

            //load the number sequences that were not generated
                seqMod.load();
            }

    5. Buke menu Organization administration/Common/Number sequences/Number sequences. Klik tombol Generate. Pilih/cari reference modul "Berita acara" dan Company yang akan dipakai. Disana akan terbaca Sequence number ID yang related pada Berita Acara. klik OK

    6. Buka modul Procurement and Sourching/Setup/Procurement parameter. Buka Tab Sequence number. disana akan ada reference baru, Berita Acara dengan Sequence Id nya.

    7. Buat Form Berita Acara. lengkap dengan table/datasourcenya (BeritaAcaraTable).
    8. Di Form BeritaAcara/Methods/, overide method close() dan numberSeqFormHandler()
    public void close()
    {
        if (numberSeqFormHandler)
        {
            numberSeqFormHandler.formMethodClose();
        }
        super();
    }
    
    NumberSeqFormHandler numberSeqFormHandler()
    {
        if (!numberSeqFormHandler)
        {

        //create a reference of number sequence form handler class specifying the         EDT, Data source name and the field of the table


        numberSeqFormHandler = NumberSeqFormHandler::newForm(NumberSeqReference::findReference(extendedtypenum(PSMGRNRevisionId)).NumberSequenceId, element,PSMGRNRevisiontable_DS,fieldnum(PSMGRNRevisiontable,PSMGRNRevisionId));
        }

    return numberSeqFormHandler;
    }    

    9. Di Datasource overwrite methods :
public void create(boolean _append = false)
{
    element.numberSeqFormHandler().formMethodDataSourceCreatePre();
    super(_append);
    element.numberSeqFormHandler().formMethodDataSourceCreate(true);
}

public void write()
{
    super();

    element.numberSeqFormHandler().formMethodDataSourceWrite();
}

public boolean validateWrite()
{
    boolean ret;

    ret = super();

    ret = element.numberSeqFormHandler().formMethodDataSourceValidateWrite(ret) && ret;

    return ret;
}

public void linkActive()
{
    element.numberSeqFormHandler().formMethodDataSourceLinkActive();
    super();
}

//untuk method deleted() dipakai jika ada table lines/detail
public void deleted()
{
    //element.numberSeqFormHandler().formMethodDataSourceDelete();
    super();
}

Erorr CS1963 - An expression tree may not contain a dynamic operation.

Kali ini saya mendapatkan erorr dengan code CS1963, padahal sebelumnya saya sudah mendefinisikan 'var item in Model' di @foreach(var...