Wednesday, June 15, 2011

Mark Customer Invoices for settlement with AX 2009 - Mark Invoices

After creating a payment journal (http://axwonders.blogspot.com/2011/06/create-axapta-payment-journal.html ), you might want to mark the invoices for settlement. This task is done by looping through the just created Payment Journal and then by querying the CustTransOpen Table and instantiating the CustTrans table from the CustTransOpen.CustTrans() method.


The following is the code to mark invoices. Also, the code loops through each payment journal transaction.

Also, the logic behind it is that the SpecTrans table needs to have two records in order to offset an open invoice with a transaction. So the code below inserts two records to the SpecTrans table. One is for all the open transactions (invoices - Sales) and the other is for all the payment transactions (paymet - Payment)

For example:

select firstonly invCustTrans where invCustTrans.AccountNum == custTable.AccountNum
            && invCustTrans.TransType == LedgerTransType::Sales
            && !invCustTrans.LastSettleDate;


the code above will select all the customer transactions with a TransType of Sales.

On the other hand, the code below will select all the customer transaction with a TransType of Payment.

select firstonly payCustTrans where payCustTrans.AccountNum == custTable.AccountNum
            && payCustTrans.TransType == LedgerTransType::Payment
            && !payCustTrans.LastSettleDate;


Then we need to insert the two instances of CustTrans into the SpecTrans table:

specOffsetVoucher.insert(invCustTrans.dataAreaId, invCustTrans.TableId, invCustTrans.RecId, invCustTrans.AmountCur, invCustTrans.CurrencyCode, NoYes::No);

specOffsetVoucher.insert(payCustTrans.dataAreaId, payCustTrans.TableId, payCustTrans.RecId, payCustTrans.AmountCur, payCustTrans.CurrencyCode, true);
The following is the whole code:

Monday, June 13, 2011

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.

Tuesday, June 7, 2011

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);
    }
}

RAID in AX 2009 - AX 2009

With an ERP system such as Microsoft Dynamics AX 2009, the database server generally stores a very large amount of important data for the business. If this data is unavailable for any length of time, the business could experience
significant financial losses.


Using a Redundant Array of Independent Disks (RAID) can help reduce the possibility of this loss occurring. Another important aspect for a database server is fine tuning for optimal performance. A RAID disk subsystem can also be used to help achieve this goal.

RAID refers to a group of two or more disks managed as a single unit to store the data together with additional, or redundant, information to provide recovery if there is a disk failure.

Usually a failed disk in a RAID system can be replaced while the server is still running. This is one benefit of RAID.

Managing Multiple AOS Instances - AX 2009

When multiple instances are installed, use the Microsoft Dynamics AX Server Configuration utility to manage all AOS instances. Use the Server Configuration utility to verify that the AOS connects to the correct database and application file server.

1. Open the Server Configuration utility (Start > Administrative Tools > Microsoft Dynamics AX Server Configuration).

2. Click Manage, click Create configuration, and then enter a name for the configuration. Then determine whether to copy it from the active or original configuration.

3. On the Application Object Server tab, validate that the Application file location is correct.

4. In the TCP/IP port field, note which port the AOS is running on.This information is needed to connect to the AOS.

5. On the Database tab, validate that the AOS is connected to the correct database. If not, change it.

6. Click OK to exit the configuration utility

Connect to a new AOS Instance - AX 2009

Follow these steps to connect a client to a new AOS instance:

1. Open the Microsoft Dynamics AX Client Configuration utility
(Start > Control Panel > Administrative Tools > Microsoft Dynamics AX Configuration Utility).

2. In the Configuration target list, select Local client.

3. Click Manage, click Create configuration, and then enter a name for the configuration. Then determine whether to copy it from the active or original configuration.

4. On the Connection tab, click New. Enter the Server name, Instance name, and TCP/IP port of the AOS instance to connect to, and then click OK and exit the configuration utility.

Create a Proxy Business Connector Account in active directory - AX 2009

Create the proxy account in Active Directory as follows:

1. Create a unique user in Active Directory in the form domain\username, for example, domain\bcproxy. This user must not have the same name as an existing Microsoft Dynamics AX user. For the procedure to add a new user, see the Active Directory documentation.

2. Assign a password to the user.

3. Select the Password does not expire option.

4. Select the No interactive logon rights option.

5. Close Active Directory

Macros in AX 2009 - AX 2009

Macros are constants, or pieces of code, that are being taken care of by the compiler before the rest of the code to replace the code where the macro is used with the content of the macro.

There are three different types of macros: stand alone macros, local macros, and macro libraries.

Macros are typically constant values that are only changed by developers. They are used so that developers don't have to hardcode these kind of values in the X++ code, but rather refer to the macro.

Inheritance in AX - AX 2009

One of the central concepts of object-oriented programming is the possibility to inherit functionality defined at a higher level in the system. This can be done by having a class hierarchy where a method in a subclass overrides a method in the super class (higher level).

The method in the subclass can still use the functionality in the same method in the super class by using the super function as in this example: