Thursday, 19 April 2012

Getting a row count from datasource

Query: How to get the total row count from form datasource.


Answer: use datasource.numberOfRowsLoaded()

Hide an element from the combo box

Question

I have an enum with values Element1, Element2 and Element3. Now this enum is being used on two different locations what the requirement is that i have to add another element Element4 in to the enum but this should only reflect on one location.

Answer
Let say you you two forms where this enum is reflected, namely Form1 and Form2. In order to hide an element from Form1 and continue showing it on Form2 go to form design and then access that combo box control. Override the enter() method of that combo box and write this line to delete the element from it.

combobox:enter()
{
super();
this.delete(enum2str(BaseEnum::Element4));
}

Create Custom Lookups Dynamics AX

One way of creating a custom lookup is by using the power of SysQuery. Lets solve this using a scenario, we want to create a customized vendor lookup that will be used on the Item form. We will define a vendor type and an item type and the vendor that matches the item type on the purchase order form shall be displayed in the lookup. So in order to get this output we will create a method lookupVendor() in the Vendor table and we will call this method from the overridden lookup() method of the Vendor.VendorId field of Vendor datasource passing in the item type from the form.
New method created in the Vendor table
public client static void lookupVendor(FormStringControl _ctrl,
VehicleVendorType _vehicleVendorType)
{

SysTableLookup sysTableLookup = SysTableLookup::newParameters(tablenum(VehicleVendor), _ctrl);
Query query = new Query();
QueryBuildDataSource qbds;
QueryBuildRange vehicleVendorFuelFilter;
;
sysTableLookup.addLookupfield(fieldnum(VehicleVendor, VendorId), true);
sysTableLookup.addLookupfield(fieldnum(VehicleVendor, VendorName));
qbds = query.addDataSource(tablenum(VehicleVendor));
switch (_vehicleVendorType)
{
case VehicleVendorType::Fuel:
qbds.addRange(fieldnum(VehicleVendor, IsFuelVendor)).value(queryValue(NoYes::Yes));
break;
case VehicleVendorType::Mantienance:
qbds.addRange(fieldnum(VehicleVendor, IsMantenanceVendor)).value(queryValue(NoYes::Yes));
break;
case VehicleVendorType::Manufacturer:
qbds.addRange(fieldnum(VehicleVendor, IsFuelVendor)).value(queryValue(NoYes::Yes));
break;
case VehicleVendorType::Tyre:
qbds.addRange(fieldnum(VehicleVendor, IsManufacturer)).value(queryValue(NoYes::Yes));
break;
case VehicleVendorType::Vehicle:
qbds.addRange(fieldnum(VehicleVendor, IsVehicleVendor)).value(queryValue(NoYes::Yes));
break;
}
sysTableLookup.parmQuery(query);
sysTableLookup.performFormLookup();
}

Overridden method of Vendor.VendorId on Vendor Datasource

public void lookup(FormControl _formControl, str _filterStr)
{
;
VehicleVendor::lookupVendor(_formControl, VehicleVendorType::Fuel);
}

Get field label in X++

Scenario: I want to use the label of a field in code.

Answer: Use SysDictField class

SysDictField dict = new SysDictField(tableId, fieldId);
str label = dict.label();

Customized Form as Dialog Box


Scenario: I need to create a runbase dialog with saving options. I need to have a runbase calling a form present in AOT.

Answer:
Override dialog method of runbase
public Object dialog()
{
FormRun dialogForm;
Args args = new Args(formstr(CustVendPaymProposalModPaymAttribDialog));
;
args.caller(this);

dialogForm = classfactory.formRunClass(args);
dialogForm.init();

return dialogForm;
}
CustVendPaymProposalModPaymAttribDialog is the dialog form which was created in order to
facilitate the design.

Dynamics AX Programming of Basic Methods of Tables



Definition and modification of methods in tables

When a new table in the Tree of Objects of the Application is created, MorphX automatically creates a series of methods for her. Adding X++ code to these methods we can modify the predetermined behavior of the system.
In addition, we can define our own methods. The methods of system and the user defined ones share he himself scope, therefore it is possible to add new methods that can be used from the methods defined by the system. As well as to accede to the system methods from any new method.
It is important to indicate that we cannot modify the type of return, the list of parameters or the type of these parameters in the methods defined by the system, although we can add additional parameters whenever we declare a value predetermined for them.

Methods of system

The system methods are executed when the table is used, for example, when we introduce, updated or erased data.
The body of these methods initially contains a call to the super method solely (). In later chapters method will be described with more east detail. To at the moment it is enough us with knowledge that corresponds to the predetermined behavior of the system. When X++ code is added to the methods defined by the system, east behavior is overloaded.
Next they appear the list of methods of system of a table. In later sections they will be described with more detail most important.
Method
It is executed when…

Caption
is the head of a form. The text is generated from the properties of the table.

Clear
the fields of the present registry erase (they have values NULL).

Delete
a registry is eliminated.

HelpField
the text of aid of a field is in the state bar, for example when we happened to the following field in a form.

InitValue
It initializes the fields of a registry just created.
Insert a new registry in the table is introduced.
Merge two registries are united or combined.
PostLoad a registry is loaded.
RenamePrimaryKey renombra the primary key of the table.
ReRead a registry is reread.
ToolTipField the leader of the mouse is located in a field of a form.
ToolTipRecord one is going away to show an advice for the present field. The super method () makes a call to Caption.
Update before modifying an existing registry.
ValidateDelete one is going away to erase a registry.
ValidateField a field give ins, for example when we jumped to the following field of a registry.
ValidateWrite before writing a registry in the data base.

Methods of validation in tables

The validation methods allow the programmer to verify that certain conditions are fulfilled before an action is executed.
In Axapta, methods of validation at two levels can be programmed:
  1. Table
  2. Origin of data of a form
It is important to know that the methods of validation of the tables are executed whenever they are introduced or erase registries. Whereas if the validation is made in the form, it will only work when we are working with that form.
  1. Whenever it is possible, the validation of data must be made in the table.

Methods

The methods of validation in tables are the following ones:
ValidateField
It is executed when we move the cursor from a field from the form to another one, that is to say, when we left a field. It gives back a data of boolean type. If the result is false, the cursor will remain in the field.
The call to the super method () verifies the validation relations, that is to say, relations in a field where the Validate property has affirmative value. Therefore, we must respect the task made by this super method ().
  1. Validations do not have to be codified that can be made with some property. Thus, we will avoid to write code in the ValidateField method if the conditions can be verified with the Validate property of a relation.
ValidateWrite
It is executed before inserting or updating a registry in the table. It gives back a data of boolean type. If it gives back false, the registry is not inserted or updates.
The call to the super method () examines all the fields to verify the value of the Mandatory property. Therefore, we must respect the task made by this super method ().
  1. We will avoid to introduce code that it verifies if a field has value, whenever we pruned to use the Mandatory property.
ValidateDelete
It is not necessary to forget, that often also we want to verify certain conditions before erasing a registry of a table. In order to do this, we used the ValidateDelete method ().
ValidateDelete () is called automatically from forms and is used to verify if the present registry can be erased.
The call to the super method () verifies if there are registries related in tables to DeleteActions of the Restricted type. If that is the case, the super method () gives back false. Therefore, we must respect the task made by this method.
  1. Whenever we pruned to use a DeleteAction, we will avoid to introduce code in the ValidateDelete method.

Structure of the validation methods

In order to maintain a good structure of programming, he is recommendable that the code for the verifications is not located directly in these methods of validation. It is more advisable than we create verification methods that will be called from the methods of validation previously described.
Example of validation method
Boolean validateWrite ()
{
Boolean ret;
ret = checkSomething () && checkSomethingElse ();
return ret;
}
When some of the conditions is not fulfilled, the verification method must make two things:
  1. to present/display to the user an error message
  2. to give back the false value like result
The CheckFailed method (`Message of error') writes the text chain that receives as parameter in the information window (Infolog) and gives back the false value. Therefore, by means of the use of this method, we obtained simultaneously both objective.
Example of use of CheckFailed
Boolean checkSomething ()
{
Boolean ret;
if (! something)
{
ret = checkFailed (`Something is wrong');
}
return ret;
}
We could use the previous structure, but cases exist in which it interests to us to verify the same Something condition, present in the CheckSomething method (), without presenting/displaying no message to the user. In this case we would need an additional method, that verified the condition but that it did not show any message.
Nevertheless, this would not be very efficient, because we would be duplicating the verification code, therefore is more recommendable to create a called method Something (), to which we will be able to call when we want, that it will be in charge to make this verification.
We will have, in addition, to change the CheckSomething method (), so that it makes a call to this new method. The CheckSomething method () we will use it solely when we want to show a message the user.
Example of complete validation
Boolean something ()
{
if (! something)
{
return false;
}
return true;
}
Boolean checkSomething ()
{
Boolean ret;
if (! something ())
{
ret = checkFailed (`Something is wrong');
}
return ret;
}
  1. We can consider a standard of nomenclature of Axapta, the use of the Check area code, in the name of all those methods that make a call to the global method CheckFailed (). Of this form we will know what methods present/display messages in the Infolog window.

Used methods of system more

Next we are going to describe some of the used methods more in the tables, that by their importance deserve a treatment something more exhaustive. The examples of the methods have been obtained from the CustTable table.
InitValue
The InitValue method is executed when we added a new registry. Also it is called automatically from the forms. Therefore, we will use the method to assign initial values or by defect in a new registry.
Example
void initValue ()
{
CustParameters custParameters;
super ();
this.languageId = CustParameters:: languageId ();
this.currency = CompanyInfo:: find () .currencyCode;
}
It is necessary to indicate that the call to the super method () does not do anything.
Insert
The Insert method is executed when a new registry in the table is introduced. It is very important to assure any related transaction to assure integrity the data base. The techniques of control of transactions will be seen in a later chapter.
Example
void insert ()
{
this.setNameAlias ();
super ();
}
If the registry cannot be inserted in the table, the call to the super method () gives back an error.
Update
The Update method is executed before modifying an existing registry in the table. In this case, also it is very important to control any related transaction to assure integrity the data base.
Example
void update ()
{
CustTable this_Orig = this.orig ();
ttsbegin;
this.setNameAlias ();
super ();
this.setAccountOnVend (this_Orig);
if (this_Orig.custGroup! = this.custGroup)
ForecastSales:: setCustGroupId (this.accountNum,
this_Orig.custGroup,
this.custGroup);
ttscommit;
}
In the example the method is used orig (). This one method gives access us to the registry before the update.
Delete
The method delete is executed when a registry is eliminated. It is very important to assure any related transaction to assure integrity to us the data base.
Let us suppose two related tables calls TableA and TableB. If in TableA we have defined a DeleteAction of type cracked (Cascade) with respect to TableB, when a registry of TableA erases erase the registries related in TableB.
For yield reasons, one is due to avoid to write code in the Delete method of these related tables (in the example, TableB). If code has not been added, the cascade erasures can be made quickly by the system database manager using directly instructions of erasure SQL.
Nevertheless, if we added code in those tables (what it can be necessary in some occasions), the system creates an instruction while select and executes the Delete method in all the tables related daughters. Of this form the yield is minor that when we directly used instructions of erasure in SQL.

Microsoft Dynamics AX Document Management System


Document management system in Microsoft Dynamics AX is used to attach documents, notes or images against specific records. All the documents are stored in DocuValue table with their reference in DocuRef table. In order to enable document management system we have to perform some simple steps.

Open Navigation Pane

Go to Basic -> Setup -> Document Management

Now you can see four options related to document management

Document types

Active document tables

Parameters

Document file extension

Now go open active document tables

Create a new entry (Ctrl + N)

Add your table in the grid and check mark active tab

Open AOT -> Data Dictionary -> Tables -> DocuRef table

open setSmmTable and place an entry of your table over here

void setSmmTable()

{

switch (this.RefTableId)

{

case tablenum(CustTable),

tablenum(VendTable),

tablenum(SalesTable),

tablenum(ProjTable),

tablenum(ContactPerson),

tablenum(smmActivities),

tablenum(SalesQuotationTable),

tablenum(smmMailings),

tablenum(smmBusRelTable),

tablenum(smmTMCallListTable),

tablenum(smmCampaignTable),

tablenum(smmEncyclopediaItems),

tablenum(smmCampaignSelection),

tablenum(yourtablename):

this.SmmTable = true;

break;

default:

this.SmmTable = false;

break;

}


}

Now you can see a document handling icon at the toolbar. You can use this icon to attach documents

Debug X++ code in a Batch Server in AX 2009

 
For example, if you want to debug the SalesFormLetter class after posting either a Packing Slip or an Invoice, you just would go to the AOT > Classes>SalesFormLetter look for the method you want to debug and add a breakpoint. Simple!

In AX 2009, however, we have the ability to run Batch jobs directly on the server (unlike prior versions (i.e. 3.5)). The problem is that to accomplish this, we have to configure a few things.

The following are the steps to accomplish debugging X++ code in a batch server. The example is going to be using the SalesFormLetter class run method.

NOTE: Please use a Development or Test environment to try these steps.

1- Open the Client Configuration Utility and Click the Manage button. Choose Create New Configuration.

2- Give it a name. (I have chose Debug2713)



3- Set the server name, instance name and port (the default for the first instance of AX will be 2712. If you have more than one instance make sure you have the right port. In my case the AX second instance is 2713)



4- Go to the developer tab and check the both "Enable user breakpoints to debug in the business connector" and "Enable global breakpoints to debug code running in the business connector or client" check boxes.



5- Now open the Server Configuration File and Click the Manage button. Choose Create New Configuration. Give it a name (i.e. Debug)

6- Set the application file location and the alternate bin directory and the Application instance. In addition, check both the "Enable breakpoints to debug X++ code running on this server" and "Enable global breakpoints to debug X++ code running in batch jobs" check boxes.



7- Click the Database Connection tab and set both the server name and database name.





8- Open the AR module and go to Periodic > Clean Up > Sales update history clean up

9- Choose the Executed Clean Up option and a date and click OK.



10- Open the AOT, go to Classes and look for the SalesFormLetter class. Open the class and look for the Run method and place a breakpoint anywhere in the code.



12- Open the AX 2009 debugger



12 - Go to AR > Common Forms and open the Sales Order Details form. Choose an Open Order and click the Post button. Choose Packing Slip (i.e.)

13 - The SalesEditForm will open. Click the Batch button and set the batch.



14- After clicking the OK button you should see the following message




If you want to check the status of your batch you can go to Basic > Inquiries >Batch Job. Your scheduled job should be in there. Wait a few minutes and the debugger should open at the breakpoint you inserted before.


NOTE: Sometimes you will have to restart the AOS service when the debugger does not open and your job has already executed. In addition, you MUST have a batch group setup.

Get the active comapny in AX 2009 - curExt()


Use the curExt() function to get the active company in AX;

static void curExtExample(Args _arg)
{
str CompanyId;
;

CompanyId = curExt();
Info(CompanyId);
}

You would also use the following with the same results. However, the above is much more elegant.

static void curExtExample(Args _arg)
{
str CompanyId;
;

CompanyId = CompanyInfo::Find().DataAreaId;
Info(CompanyId);
}

Unable to validate the AX 2009 Workflow Webservice URL on a Windows Server 2008 R2 x64 - The request failed with HTTP status 405: Method Not Allowed

.

Hi,

I was having some issues yesterday validating an URL in Windows Server 2009 R2 - 64. I have done this a few times already and the process have been really smooth and straight forward. However, in the environment I'm working on right now I the The request failed with HTTP status 405: Method Not Allowed error.

I found this post that helped me solve the problem, which basically was changing the property value of the MicrosoftDynamicsAXWorkflow50 application pool in IIS Manager to "Enable 32-Bit Applications".

Here is the link:

http://blogs.msdn.com/b/emeadaxsupport/archive/2010/01/05/unable-to-validate-the-ax-2009-workflow-webservice-url-on-a-windows-server-2008-r2-x64.aspx

Error code 122 - AX 2009


While modifying some code on my devlopment machine i came across the following error...
Error in file: D\MDAX\AppFiles\..while writing in record = 336985 Windows error: = Error code: 112 = Unknown Error
 The above error (based on the msdn description) means that the disk is full (ERROR_DISK_FULL: There is not enough space on the disk)
The problem is that the AOS is trying to save the changes I making to my code into the *aod files, but there is not enough space on the hard disk (in my case D) for it to accomplish that.
We can solve this problem by freeing up disk space on the AOS machine.

AX 2009 Data Import / Export


The following post is about shows how to:
1-   Export data from a company in AX using a definition Group
2-   Creating a new company that will take the new data
3-   Importing the data exported from step 1 into the new company created in step 2 using a definition group as well.
In a current project, I needed to freeze the Test1 environment due to some focus testing of a certain functionality we implemented. At the same time, we needed to allow the uses to keep testing other customizations without affecting Test1.
In addition, to make the user’s lives easier, we decided to have the same data that they were using in Test1 in our Test2 instance. So, we exported the data from our Test1 environment, and then imported it to a new company in our Test2 environment.
The following steps will show this process step by step:

1-   First select the company you want to export the data from as the AX current company by clicking in company name in the right lower corner of your AX interface.

2-   This would open the “Select Company” form as shown;

3-   Select  Administration (module)
4-   Under periodic->Data exports /import ->Click Export to
5-   The “Export options” form will appear
6-   Select a definition group. You can either create a new definition group to include what you need, or just choose ALL to get all the tables.

NOTE: In some cases, the already defined “ALL” definition group will not have all the tables, so in this case you would have to create a new definition group. In my case I created a new one name “ALL_NewDef” that included the latest tables.

7-   Enter a file name and select where to save it
8-   Click OK. At this point the company date export process should be done (after processing of course), and the files (.dat & .def) should have be saved on your computer.

Now, let’s create a new company

9-   Make sure that the selected company empty and click area node Administration
10- Click company Accounts under Common forms
11-   Press (Ctrl + N) in order to Create new company
12-   Make sure you select the newly created company as the current company

Import company file already exported in the prior steps and click Administration

13- Under periodic->Data exports /import ->Click import; The “Import options” screen will appear
14- Select the “import definition group” drop down list and choose ALL (otherwise create your own)
15-   Select the .dat file (exported before) and Click Ok to start the process

The import process may take some time according to the size of transactions in the original (exported) company.
In addition, you can choose to delete all the transaction data before the import when you are importing a .dat file o an existing company account to update the data.

Code to refresh system tables in AX 2009 - SysClientSession Table


The following code will refresh the system tables in AX 2009. I had an issue with the SysClientSession table this morning and I found some documentation about from Microsoft where they suggest running a script to allow the syscronozation of systables.

The kernel uses the SYSTABVERSION parameter value in the SQL SystemVariables table to synchronize its list with the DataBase

The following were the errors I got:

1- The database reported (session 1 (-AOS-)): [Microsoft][SQL Native Client][SQL Server]Invalid object name 'SYSCLIENTSESSIONS'.. The SQL statement was: "SELECT A.SESSIONID,A.SERVERID,A.VERSION,A.LOGINDATETIME,A.LOGINDATETIMETZID,A.STATUS,A.USERID,A.SID,A.USERLANGUAGE,A.HELPLANGUAGE,A.CLIENTTYPE,A.SESSIONTYPE,A.CLIENTCOMPUTER,A.RECVERSION,A.RECID FROM SYSCLIENTSESSIONS A WHERE (SERVERID=?)"

2- Internal Error occurred executing stored procedure when creating session for the AOS.

Please backup your DB before running this script.

update SqlSystemVariables set value = value - 1 where parm = 'systabversion'

Once you do this please restart your AOS and the problem should be fixed.

AX 2012 - New Improvements in Data Security


The new version of AX offers many new features to all of us. These go from development improvements to data security, which is the one topic I would like to focus on in this post.

The following are the improvements with regard to data security:
  • Role-based security
  • Server-enforced security
  • Extensible data security framework
  • Flexible authentication

Role-based security
Data security is much easier to manage. In AX 2012, users are assigned to roles based on the duties and responsibilities they have and access is granted based on those roles. This change puts an end to the tedious and time-consuming process of assigning users based on application objects. Once set up, role assignments can easily be updated based on the business data.


Server-enforced security
Authorization is performed on the server rather the client, consistently enforcing permissions on protected fields regardless of the type of client. The server sends the client only the information that the user has been granted access to, resulting in increased data security.


AX 2009 did not offer the facility to use data security based on effective date. However, in AX 2012 administrators can specify whether users have access to past, present, or future records with different levels of access, which creates much for flexibility to all the different iteration in the use of data throughout the life of the application.

Further, the new version can also be used to create data security policies based on data contained in a different table.

For example, in previous versions you could not filter sales lines by customer location because those were stored in different tables, but the new version makes that totally possible.

Data security policies are enforced at the server regardless of the type of client used to access the data.

Flexible authentication
Authentication of users by methods other than Active Directory allowing external users to access Dynamics AX without a required domain account.

Ax 2009 SSRS Videos


While looking for some information related to AX 2009 SSRS I found a bunch of videos related to SSRS and AX 2009.

Here is the link:

http://youtu.be/ZIoEZWaiBXI

LIKE Operator in X++


In Axapta, we can use the LIKE operator in an inline SQL statement, see the following:


select * from VendTable where VendTable.Name like 'P*'


Another example is to use the LIKE operator to compare strings!


static void MyTestForLike(Args _args)
{


    str test;
    ;

    test="Eduardo";

    if(test like "Eduar*")
       info('Hello Ed!');


}

strRem Function - Delete a Character from String - AX 2009


The following code searches a specified string character and deletes it. The cool thing about this function is that it is case sensitive.


str strRem(str text1, str text2)
text1  The string from which to remove characters.
text2 The characters to exclude from the output string.

For example:

strRem("MynameIs","is"); //Returns the string "MynameI".

Create loop from an AX form DataSet - Ax 2009


Sometimes we need to loop through values at the form level. The following code loops (for loop) the SalesParmTable in the CloseOk() Form method.        


        //Create Lines
        for (localSalesParmTable = salesParmTable_ds.getFirst();
              localSalesParmTable;
              localSalesParmTable = salesParmTable_ds.getNext())
        {

              ....Implementation....
        }

Using Args for Output and Display Menuitems - AX 2009


public static void main(Args args)
{
    VendPurchOrderJour      vendPurchOrderJour;
    PurchTable              purchTable;
    ;
    if(args.dataset() == tablenum(VendPurchOrderJour))
    {
        vendPurchOrderJour = args.record();
        select purchTable where purchTable.PurchId == vendPurchOrderJour.PurchId;
        if(purchTable.CustomsImportOrder_IN == noYes::Yes)
            new MenuFunction(menuitemoutputstr(TestPurch), MenuItemType::Output).run(args);
        else
            new MenuFunction(menuitemoutputstr(TestS), MenuItemType::Output).run(args);
    }
}

Using Args for Output and Display Menuitems - AX 2009


public static void main(Args args)
{
    VendPurchOrderJour      vendPurchOrderJour;
    PurchTable              purchTable;
    ;
    if(args.dataset() == tablenum(VendPurchOrderJour))
    {
        vendPurchOrderJour = args.record();
        select purchTable where purchTable.PurchId == vendPurchOrderJour.PurchId;
        if(purchTable.CustomsImportOrder_IN == noYes::Yes)
            new MenuFunction(menuitemoutputstr(TestPurch), MenuItemType::Output).run(args);
        else
            new MenuFunction(menuitemoutputstr(TestS), MenuItemType::Output).run(args);
    }
}

Create Axapta Payment Journal


The following code creates a payment journal in AX.

public void PaymentJournalLineCreation()
{
    boolean                     ret;
    CustTable                   custTable;
    LedgerJournalName           LedgerJournalName;
    LedgerJournalTable          ledgerJournalTable;
    LedgerJournalTrans          ledgerJournalTrans;
    LedgerJournalCheckPost      ledgerJournalCheckPost;
    NumberSeq numberseq;

    ;

    //Get customer account
    this.getCustomerAccount();

    //Get currency
    this.setCurrency();

    //Set JournalNameId
    this.setJournalNameId(LedgerJournalACType::Bank);

    //Get table buffer
    custTable = CustTable::find(customerAccount, false);

    // Find a ledgerJournalName record
    select firstonly LedgerJournalName
    where LedgerJournalName.JournalName == journalNameId;


    //Get next available voucher number
    numberseq = NumberSeq::newGetVoucherFromCode(LedgerJournalName.VoucherSeries);
    ledgerJournalTrans.Voucher = numberseq.voucher();

    //Generate the transaction line
    ledgerJournalTrans.JournalNum = ledgerJournalId;
    ledgerJournalTrans.CurrencyCode = currencyCode;
    ledgerJournalTrans.ExchRate = Currency::exchRate(ledgerJournalTrans.CurrencyCode);

    ledgerJournalTrans.AccountNum = customerAccount;
    ledgerJournalTrans.accountName();
    ledgerJournalTrans.AccountType = LedgerJournalACType::Cust;

    ledgerJournalTrans.Dimension[1] = custTable.Dimension[1];
    LedgerJournalTrans.KUMTeamDescription();
    ledgerJournalTrans.Dimension[2] = custTable.Dimension[2];
    ledgerJournalTrans.KUMDetailDescription();
    ledgerJournalTrans.Dimension[3] = custTable.Dimension[3];
    ledgerJournalTrans.KUMEventDescription();

    ledgerJournalTrans.AmountCurCredit = paymentAmount;
    ledgerJournalTrans.TransDate = PaymentDate;
    ledgerJournalTrans.Txt = '@COL1576'; //Payment, Thank you
    ledgerJournalTrans.PaymMode = custTable.PaymMode;
    ledgerJournalTrans.PostingProfile = 'DFLT';
    ledgerJournalTrans.BankTransType = 'Chck-rcpt';
    ledgerJournalTrans.Payment = custTable.PaymTermId;
    ledgerJournalTrans.CustVendBankAccountId = this.GetCustomerBankAccountID(customerAccount);
    ledgerJournalTrans.SettleVoucher = SettlementType::OpenTransact;
    ledgerJournalTrans.TransactionType = LedgerTransType::Payment;
    ledgerJournalTrans.Approved = NoYes::Yes;
    ledgerJournalTrans.ApprovedBy = curUserId();
    ledgerJournalTrans.Due = systemdateget();
    ledgerJournalTrans.TaxGroup = 'DFLT';

    ledgerJournalTrans.OffsetAccount = bankAccount;
    ledgerJournalTrans.OffsetAccountType = LedgerJournalACType::Bank;
    ledgerJournalTrans.offsetAccountName();

    ledgerJournalTrans.PaymentStatus = CustVendPaymStatus::None;
    ledgerJournalTrans.insert();

}
There are some methods calls in the previous code. These are the following:
//Find customer account based on Customer Reference Number
public CustAccount getCustomerAccount()
{
    CustAccount     custAccount;
    CustBankAccount custBankAccount;
    int             countRecords = 0;
    ;

    switch (JournalFormatType)
    {
        case KMN_CustPaymentJournalFormatType::Mexico:
            select * from custBankAccount where custBankAccount.MsgToBank == customerReference;
            custAccount = custBankAccount.CustAccount;
            this.parmCustAccount(custAccount);
            break;
    }

    return custAccount;
}

//Sets the currency value to the property
public void setCurrency()
{
    ;
    //Set property
    this.parmCurrencyCode(CompanyInfo::standardCurrency());
}

public void setJournalNameId(LedgerJournalACType _journalType)
{
    LedgerJournalNameId _journalNameId;
    ;
    switch(_journalType)
    {
        case LedgerJournalACType::Bank:
            _journalNameId = 'CR';
            break;

    }

    this.parmLedgerJournalNameId(_journalNameId);
}

NOTE: I'm using accessory methods for most of the variables in this code (this is a class), so remember to declare them in the classDeclaration and create your own properties.