Wednesday, March 17, 2021

How get primary email of customer or vendor

Below code is for customer only, for vendor we need to replace CustTable with VendTable.  

dirPartyContactInfoView        dirPartyContactInfoView;

CustTable custTable;

        select firstOnly Locator dirPartyContactInfoView

        order by dirPartyContactInfoView.IsPrimary desc

            where dirPartyContactInfoView.Party == custTable.Party &&

            dirPartyContactInfoView.Type == LogisticsElectronicAddressMethodType::Email;

        

      custAccountStatementExtTmp.CustEmail = dirPartyContactInfoView.Locator;

Sunday, March 14, 2021

Sequence of calling form methods in AX 2012

 

This gives the information of method calls in the form level while
1. Opening the Form.

2. Creating/Updating/Deleting the record in the Form.

3. Closing the Form.

Sequence of Methods calls while opening the Form

Form --- init ()
Form --- Datasource --- init ()
Form --- run ()
Form --- Datasource --- execute Query ()
Form --- Datasource --- active ()

Sequence of Methods calls while closing the Form

Form --- canClose ()
Form --- close ()

Sequence of Methods calls while creating the record in the Form

Form --- Datasource --- create ()
Form --- Datasource --- initValue ()
Table --- initValue ()
Form --- Datasource --- active ()

Sequence of Method calls while saving the record in the Form

Form --- Datasource --- ValidateWrite ()
Table --- ValidateWrite ()
Form --- Datasource --- write ()
Table --- insert ()

Sequence of Method calls while deleting the record in the Form

Form --- Datasource --- validatedelete ()
Table --- validatedelete ()
Table --- delete ()
Form --- Datasource --- active ()

Sequence of Methods calls while modifying the fields in the Form
Table --- validateField ()
Table --- modifiedField ()

Purchase requisition

  

Purchase requisition overview

A purchase requisition is an internal document that authorizes the Purchasing department to buy items or services.

After a purchase requisition is approved, it can be used to generate a purchase order. Purchase orders are the external documents that the Purchasing department submits to vendors.

You can create a purchase requisition by select the items and services that you require. You can select items from a procurement catalog that your organization has created, or you can request items that aren't found in a catalog by selecting a procurement category and entering the product details.

Before submitting a purchase requisition for review, workflows must be configured. You use a workflow to move a purchase requisition through the review process, from an initial status of Draft to a final status of Approved.

You can configure the purchase requisition workflow process to route a purchase requisition through the review process as a single document. Alternatively, the lines on a purchase requisition can be routed individually to the appropriate reviewers. If the purchase requisition lines are reviewed individually, the status of each purchase requisition line can be updated as the line moves through the review process.

 

 

 

 

 

 

 

 

 

 

Purchase requisition workflow

 

The following diagram shows the statuses that are assigned to a purchase requisition and a purchase requisition line as they move through the workflow process.

 

 

 

 

 

 

 

 

 

 

 

Purchase requisition header and line status relationships

 

The overall status of a purchase requisition is determined by the status of the purchase requisition lines. Therefore, the review process must be completed for all purchase requisition lines before the review process for the whole purchase requisition can be completed. The following table describes the statuses that are assigned to a purchase requisition header and lines as the purchase requisition moves through the workflow process.

 

Purchase requisition status

Purchase requisition line status

Description

Draft

Draft

The purchase requisition and purchase requisition line have been created, but they haven't been submitted for review. Purchase requisitions and purchase requisition lines that have a status of Draft can be modified. A purchase requisition or purchase requisition line also has a status of Draft if it has been recalled but hasn't been resubmitted for review. Note: You can submit or recall a purchase requisition at the document level. However, you can't submit or recall a single purchase requisition line.

In review

·        In review

·        Rejected

If the workflow has been configured to route purchase requisition lines to individual reviewers, each line can have a status of In review or Rejected. The purchase requisition status is updated when the review process is completed for all purchase requisition lines and no review steps remain for the purchase requisition.

·        In review – The purchase requisition lines have been submitted for review. When the workflow process is completed for a purchase requisition line, the status of that line remains In review until all remaining purchase requisition lines have been reviewed.

·        Rejected – A purchase requisition line has been rejected. Purchase requisition lines that are rejected can be modified and resubmitted.

If you resubmit a purchase requisition line that has been rejected, the review process starts over for all lines in the purchase requisition that are still in review.
Note: You can recall a purchase requisition that has already been submitted. When you recall a purchase requisition, all other purchase requisition lines are also recalled. Purchase requisition lines that have been recalled can be deleted.

Rejected

Rejected

The purchase requisition and all purchase requisition lines have been rejected. Purchase requisitions and purchase requisition lines that have been rejected can be resubmitted.

Approved

·        Approved

·        Cancelled

·        Closed

All purchase requisition lines have completed the review process, and there are no more review steps for the purchase requisition.

·        Approved – The review process for a purchase requisition line has been completed, and the line is approved.

·        Cancelled – The purchase requisition line was approved, but it has been canceled because it's no longer required. Only purchase requisition lines that have been approved can be canceled.

·        Closed – The purchase requisition line was approved, and documents have been generated, depending on the requisition purpose.

o   If the requisition purpose is consumption, a purchase order has been generated for the purchase requisition line.

o   If the requisition purpose is replenishment, one or more fulfillment documents have been generated.

Cancelled

Cancelled

The purchase requisition and all purchase requisition lines have been canceled.
Note: If you no longer require an item that is on a purchase requisition line, you must cancel the purchase requisition line if it has already been approved. Only purchase requisition lines that have been approved can be canceled. If any purchase requisition lines are in review, the purchase requisition will have a status of In review. In this case, you can recall the purchase requisition and delete the appropriate purchase requisition line.

Closed

·        Closed

·        Cancelled

The purchase requisition is closed, and one or more fulfillment documents have been generated.

·        Closed – The purchase requisition line was approved, and documents have been generated, depending on the requisition purpose.

o   If the requisition purpose is consumption, a purchase order has been generated for the purchase requisition line.

o   If the requisition purpose is replenishment, one or more fulfillment documents have been generated.

·        Cancelled – The purchase requisition line was approved, but it has been canceled because it's no longer required. Only purchase requisition lines that have been approved can be canceled.

Note: If you no longer require an item on a purchase requisition line that has been closed, you must cancel the line on the fulfillment document that was generated for the purchase requisition line.

 

 

 

 

 

 

 

 

 

Distributing costs to multiple financial accounts

You can distribute the cost of a product that is included in a purchase requisition to multiple financial accounts. If your organization uses dimensions, such as cost centers and departments, you can distribute the cost of a product to dimensions for financial accounts

 

Requisition purposes

Requisition purposes make the process of fulfilling requisition demand more flexible. When you create a requisition, you can assign one of two purposes to it: consumption or replenishment. Depending on the requisition purpose and the setup of your organization, requisition demand can be fulfilled by a purchase order, transfer order, production order, or kanban.

In the procurement policies, you can control the requisition purposes that are available when a requisition is created for your organization.

 

Requisitions that have a purpose of consumption

A requisition that has a purpose of consumption represents demand for items or services that will be used internally by your organization. The demand that is created by this kind of requisition is always fulfilled by a purchase order. If Supply Chain Management is set up to automatically generate purchase orders, purchase orders are created after the purchase requisition is approved.

 

Purchase order

 

 Purchase order overview

            A purchase order (PO) is an agreement with a vendor to buy goods or services. This helps keep track of product receipts that are made toward the order and, later, the accounting of vendor invoices that the vendor bills toward the order.

 

Create the purchase order header

1.      Go to Navigation pane > Modules > Procurement and sourcing > Purchase orders > All purchase orders.

2.      Select New.

3.      Select vendor account US-101. When you select a vendor, details from the vendor record such as address, invoice account, delivery terms, and delivery mode will be copied as default values into the order header. You can change these values at any time.

4.      Expand the General section.

a.      The Site field together with the Warehouse field specifies where the procured goods or services must be delivered to. The default delivery address is the site. Both fields can be populated with values set up for the selected vendor, or you can specify them manually.

b.     The Delivery date field is used to specify when procured goods and services need to be delivered. You can specify a single delivery date for the order, or the individual order lines can be given unique delivery dates. If the delivery date specified here cannot be met for specific products or services because they have longer lead times, then those lines will be created with a later delivery date to accommodate for this.

5.      Expand the Administration section. The Orderer field can be used to specify who is placing the order. This may be convenient to share with the vendor in case they need to contact that person. The field may be assigned a value automatically if the current user account is associated with a name on the Users page.

6.      Select OK. The order header has now been created. When you work with purchase order lines, only a summary of the header information is shown. If you need to view the rest of the information, select Header.

 

Add a purchase order line

1.      Select Purchase order line.

2.      Select Dimensions. Products can be in variants that are differentiated by dimensions, such as color, size, or style. Products can also be set up to use storage dimensions, such as site and warehouse. There are also optional tracking dimensions, such as batch and serial numbers. To improve the efficiency of order entry, you can add the dimension fields that you commonly use directly to the order grid.

3.      Select the Color check box. Optional: If you select the Save setup field, the dimensions you have chosen will also be shown on the order line grid the next time you open the purchase order page.

4.      Select OK.

5.      In the Item number field, select T0004.

a.      Order lines are created for products and services by specifying an item number, or as expenses by specifying a procurement category.

b.     The Procurement category field is used for adding lines where procured items are expensed directly, rather than going into inventory. This means that if you need to expense a purchase you can do this by creating a purchase order line that specifies a procurement category, rather than creating a line with an item number. Items can also be associated with a procurement category and in this case, the procurement category is shown as informational only.

6.      In the Color field, enter or select a value. The Site and Warehouse fields are typically populated with values from the order header, but it is possible to override the fields if some lines need to be delivered to different locations.

7.      In the Quantity field, enter a number.

a.      Select the quantity that you want to purchase. The Quantity field is automatically populated with the minimum order quantity for the product if this is set up, or with the value of 1.

b.     The Unit field indicates the unit of measure for the ordered quantity. Typically, the unit is automatically provided from the purchasing unit on the product master data, but you can change this.

c.      The Unit price field typically contains a value from either a purchase agreement or a trade agreement. It's possible to change the unit price on individual order lines, for example if a unique price is negotiated with the vendor.

d.     The Discount field represents a discount amount per unit. This discount therefore reduces the unit price by the discount. This discount is commonly supplied automatically from purchase agreements or trade agreements, but it is possible to override on individual lines if unique discounts have been negotiated with the vendor.

e.      A discount percentage can be entered that reduces the net amount for the line accordingly. The discount percent is often supplied automatically from purchase agreements or trade agreements, but it is possible to override on individual lines if a unique discount percentage has been negotiated with the vendor.

f.       The value in the Net Amount field is calculated from other fields on the line including quantity, unit price, discount, and discount percent. It's possible to change the Net amount, but then the Unit PriceDiscount, and Discount percent fields will be blank and when you post toward the line, the amount posted will be proportional to the net amount. Typically, the Net Amount field is only used for displaying the net amount of the line.

8.      Expand the Line details section.

9.      Select the Delivery tab. A unique delivery date can be assigned to each order line. The date is inherited from the field on the purchase order header, but you can change this.

 

Review order totals

1.      Select Totals.

a.      If you don't see the Totals action, select the Purchase Order tab on the Action Pane.

b.     This dialog box shows totals for the whole order.

c.      The Selection field allows you to change the basis of how totals are calculated. For example, you could choose Product receipt quantity to show totals that relate to the amount of the product(s) that have been received or Ordered quantity to show the amount of product that was ordered.

2.      Select OK.

 

ExtensionOf versus extends

 "extends" is about inheritance in the usual object-oriented way. You create a new class inheriting from the base class and you can use it anywhere where you can use the parent class. For example, if a method accepts a parameter of type BaseClass, you can put there an object of ChildClass (if ChildClass extends BaseClass). But you can't change anything in BaseClass itself; you can merely add things or redefine existing methods in BaseClass.

Unlike inheritance, ExtensionOf is something completely specific to Dynamics 365 for Finance and Operations. Although you can't physically change BaseClass (because it's typically in a completely different DLL), class extension allow you to pretend that you added things like methods to BaseClass. Note that you won't be using a new type like with inheritance. Instead of adding things to ChildClass, you add them directly to BaseClass and instances of BaseClass will get the new methods, fields etc.

Inheritance didn't get deprecated by any mean; class extensions solve a different problem. They allow you to add capabilities even to classes where you don't control instantiation (= you can't use ChildClass instead of BaseClass) because the application wasn't designed for extensibility.





Source:

ExtensionOf versus extends - Dynamics 365 Finance Forum Community Forum

Form extensions

 We can extend the functionality of a form by extending its controls and data sources. For example, in a form extension, we can:

  • Add a new control.
  • Enable or disable a control.
  • Change the text or label property of a control.
  • Change a control's visibility.
  • Change a form's help text.
  • Change a form's caption.
  • Add a new data source.
  • Add a form part.

Monday, March 8, 2021

Customer Aging Report











 /// <summary>

/// Extension of <c>CustVendBalanceList</c> class

/// </summary>

[ExtensionOf(classStr(CustVendBalanceList))]

final class CustVendBalanceList_CustomerAging_Extension

{

    /// <summary>

    /// numOfBalanceAge

    /// </summary>

    /// <returns></returns>

    public static Counter numOfBalanceAge()

    {

        next numOfBalanceAge();


        const Counter MaximumNumberOfAgingBalances = 9 ;


        return MaximumNumberOfAgingBalances;

    }


}



/// <summary>

/// Extension of <c>CustPostInvoice</c> class

/// </summary>

[ExtensionOf(classStr(CustBalanceList))]

final class CustBalanceList_CustomerAging_Extension

{

    public AccountSumMap_CustomerAging tmpAccountSum_CustomerAging;


    /// <summary>

    /// Constructs the contract that maps aging buckets to their corresponding fields in the <c>CustTmpAccountSum</c> table buffer.

    /// </summary>

    /// <returns>The <c>CustVendBalanceListBucketToBalanceFieldReturn</c> instance with the map of bucket to fields.</returns>

    [Wrappable]

    protected final CustVendBalanceListBucketToBalanceFieldReturn buildBucketToBalanceFieldsMap()

    {

        CustVendBalanceListBucketToBalanceFieldReturn bucketsToFields =  next buildBucketToBalanceFieldsMap();


        bucketsToFields.addBucket(7,

            this.constructCustVendBalanceListBalanceFieldsParameters_CustomerAging(fieldNum(CustTmpAccountSum, CustAgingBalance08),

                fieldNum(CustTmpAccountSum, CustAgingBalance08Cur),

                fieldNum(CustTmpAccountSum, CustAgingBalance08ReportingCurrency)));


        bucketsToFields.addBucket(8,

            this.constructCustVendBalanceListBalanceFieldsParameters_CustomerAging(fieldNum(CustTmpAccountSum, CustAgingBalance09),

                fieldNum(CustTmpAccountSum, CustAgingBalance09Cur),

                fieldNum(CustTmpAccountSum, CustAgingBalance09ReportingCurrency)));


        return bucketsToFields;

    }


    /// <summary>

    /// constructCustVendBalanceListBalanceFieldsParameters_CustomerAging

    /// </summary>

    /// <param name = "_balanceAmountMSTField"></param>

    /// <param name = "_balanceAmountCurField"></param>

    /// <param name = "_balanceReportingAmountField"></param>

    /// <returns></returns>

    private CustVendBalanceListBalanceFieldsParameters constructCustVendBalanceListBalanceFieldsParameters_CustomerAging(FieldId _balanceAmountMSTField, FieldId _balanceAmountCurField, FieldId _balanceReportingAmountField)

    {

        CustVendBalanceListBalanceFieldsParameters param = CustVendBalanceListBalanceFieldsParameters::construct();

        param.balanceMSTField = _balanceAmountMSTField;

        param.balanceCurField = _balanceAmountCurField;

        param.balanceReportingCurrencyField = _balanceReportingAmountField;


        return param;

    }


    /// <summary>

    /// COC for insertIntoTmpAccountSumV2

    /// </summary>

    /// <param name = "_agingCalculation"></param>

    /// <param name = "_withAmountCur"></param>

    /// <param name = "_withAmountMST"></param>

    /// <param name = "_withAmountMSTSecondary"></param>

    /// <param name = "_toCustVendTable"></param>

    protected void insertIntoTmpAccountSumV2(CustVendAgingCalculation _agingCalculation, boolean _withAmountCur, boolean _withAmountMST, boolean _withAmountMSTSecondary, CustVendTable _toCustVendTable)

    {

        next insertIntoTmpAccountSumV2(_agingCalculation, _withAmountCur, _withAmountMST, _withAmountMSTSecondary, _toCustVendTable);


        tmpAccountSum_CustomerAging = custTmpAccountSum;

    }


    /// <summary>

    /// getSpecificSourceCurrency

    /// </summary>

    /// <param name = "_accountNum"></param>

    /// <param name = "_currencyCode"></param>

    /// <param name = "_isSourceCurrency"></param>

    /// <returns></returns>

    public container getSpecificSourceCurrency(AccountNum _accountNum, CurrencyCode _currencyCode, boolean _isSourceCurrency)

    {

        

        next getSpecificSourceCurrency(_accountNum, _currencyCode, _isSourceCurrency);


        

        if (_isSourceCurrency)

        {

            select sum(Balance02Cur),

                sum(Balance03Cur),

                sum(Balance04Cur),

                sum(Balance05Cur),

                sum(Balance06Cur),

                sum(Balance07Cur),

                    sum(CustAgingBalance08Cur),

                    sum(CustAgingBalance09Cur)

            from tmpAccountSum_CustomerAging

            where tmpAccountSum_CustomerAging.AccountNum == _accountNum

                && tmpAccountSum_CustomerAging.CurrencyCode == _currencyCode;


            return [tmpAccountSum_CustomerAging.Balance02Cur, tmpAccountSum_CustomerAging.Balance03Cur, tmpAccountSum_CustomerAging.Balance04Cur, tmpAccountSum_CustomerAging.Balance05Cur, tmpAccountSum_CustomerAging.Balance06Cur, tmpAccountSum_CustomerAging.Balance07Cur, tmpAccountSum_CustomerAging.CustAgingBalance08Cur, tmpAccountSum_CustomerAging.CustAgingBalance09Cur];

        }

        else

        {

            select sum(Balance02),

                    sum(Balance03),

                    sum(Balance04),

                    sum(Balance05),

                    sum(Balance06),

                    sum(Balance07),

                    sum(CustAgingBalance08),

                    sum(CustAgingBalance09)

            from tmpAccountSum_CustomerAging

            where tmpAccountSum_CustomerAging.AccountNum == _accountNum

                && tmpAccountSum_CustomerAging.CurrencyCode != _currencyCode;


            return [tmpAccountSum_CustomerAging.Balance02, tmpAccountSum_CustomerAging.Balance03, tmpAccountSum_CustomerAging.Balance04, tmpAccountSum_CustomerAging.Balance05, tmpAccountSum_CustomerAging.Balance06, tmpAccountSum_CustomerAging.Balance07, tmpAccountSum_CustomerAging.CustAgingBalance08, tmpAccountSum_CustomerAging.CustAgingBalance09];

        }

    }


}



/// <summary>

/// Extension of <c>CustAgingSnapshot</c> class

/// </summary>

[ExtensionOf(classStr(CustAgingSnapshot))]

final class CustAgingSnapshot_CustomerAging_Extension

{

    /// <summary>

    /// Populates the aging period fields on the <c>CustAging</c> table buffer.

    /// </summary>

    /// <param name = "_custAging">The <c>CustAging</c> table buffer to populate.</param>

    /// <param name = "_columnToAgingPeriodArray">The array storing values for aging period values.</param>

    /// <param name = "_columnToAgingPeriodReportingArray">The array storing values for the reporting currency period values.</param>

    [Wrappable(true)]

    protected final void populateAgingPeriodFieldsForSnapShot(CustAging _custAging,

        Array _columnToAgingPeriodArray,

        Array _columnToAgingPeriodReportingArray)

    {

        next populateAgingPeriodFieldsForSnapShot(_custAging, _columnToAgingPeriodArray, _columnToAgingPeriodReportingArray);

        

        _custAging.AgingPeriod7 += _columnToAgingPeriodArray.value(7);

        _custAging.AgingPeriod8 += _columnToAgingPeriodArray.value(8);

    }


}



/// <summary>

/// CustAgingReportDP_CustomerAging_Extension

/// </summary>

[ExtensionOf(ClassStr(CustAgingReportTmpFromCustTmpAccountSum))]

final class CustAgingReportTmpFromCustTmpAccountSum_CustomerAging_Extension

{

    private static CustAgingReportDPParameters CustAgingReportDPParameters_CustomerAging;

    private static CustAgingReportTmpFromCustTmpAccountSum instance_CustomerAging;


    /// <summary>

    /// Creates a new instance of the <c>VendTmpAccountSumFromVendAgingReportTmp</c> class.

    /// </summary>

    /// <param name = "_custAgingReportDPParameters">

    /// An instance of <c>CustAgingReportDPParameters</c> object.

    /// </param>

    /// <returns>

    /// The instantiated <c>CustTmpAccountSumFromCustAgingReportTmp</c> object.

    /// </returns>

    public static CustAgingReportTmpFromCustTmpAccountSum newFromCustAgingReportDP(CustAgingReportDPParameters _custAgingReportDPParameters)

    {

        instance_CustomerAging = next newFromCustAgingReportDP(_custAgingReportDPParameters);

        CustAgingReportDPParameters_CustomerAging=_custAgingReportDPParameters;

        return instance_CustomerAging;

    }


    /// <summary>

    /// initFieldMapping method

    /// </summary>

    protected void initFieldMapping()

    {

        int custTmpAccountSumDataSourceId = this.getCustTmpAccountSumDataSourceId();


        if (CustAgingReportDPParameters_CustomerAging.reverseAmountsAndHeadings)

        {

            if (CustAgingReportDPParameters_CustomerAging.ledgerCurrencySelection == LedgerCurrencySelection::Accounting)

            {

                this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance08), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging1));

                this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance09), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging2));

            }

            else if (CustAgingReportDPParameters_CustomerAging.ledgerCurrencySelection == LedgerCurrencySelection::Reporting)

            {

                this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance08ReportingCurrency), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging1));

                this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance09ReportingCurrency), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging2));

            }


            this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance08Cur), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging1Cur));

            this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance09Cur), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging2Cur));

        }

        else

        {

            if (CustAgingReportDPParameters_CustomerAging.ledgerCurrencySelection == LedgerCurrencySelection::Accounting)

            {

                this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance08), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging1));

                this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance09), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging2));

            }

            else if (CustAgingReportDPParameters_CustomerAging.ledgerCurrencySelection == LedgerCurrencySelection::Reporting)

            {

                this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance08ReportingCurrency), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging1));

                this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance09ReportingCurrency), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging2));

            }


            this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance08Cur), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging1Cur));

            this.insertFieldMap(custTmpAccountSumDataSourceId, tableNum(CustTmpAccountSum),  fieldNum(CustTmpAccountSum, CustAgingBalance09Cur), tableNum(CustAgingReportTmp), fieldNum(CustAgingReportTmp, BalanceCustomerAging2Cur));

        }


        next initFieldMapping();

    }


}


/// <summary>

/// CustAgingReportDP_CustomerAging_Extension

/// </summary>

[ExtensionOf(ClassStr(CustAgingReportDP))]

final class CustAgingReportDP_CustomerAging_Extension

{

    public TransDate HeadingCustomerAging1;

    public TransDate HeadingCustomerAging2;

    public TransDate HeadingCustomerAging4;

    public TransDate HeadingCustomerAging3;

    public TransTxt HeadingAgingBucketDescriptionCustomerAging1;

    public TransTxt HeadingAgingBucketDescriptionCustomerAging2;

    public TransDate tempHeadingCustomerAging3;


    #define.emptyString(' ')


    /// <summary>

    /// Inserts records into the temporary <c>CustAgingReportTmp</c> table.

    /// </summary>

    /// <param name="_reverseAmountsAndHeadings">

    /// A Boolean value that indicates whether the column values should be reversed.

    /// </param>

    /// <returns>

    /// The custAgingReportTmp transaction that needs to be inserted.

    /// </returns>

    protected CustAgingReportTmp insertCustAgingReportTmp(boolean _reverseAmountsAndHeadings)

    {

        HeadingAgingBucketDescriptionCustomerAging1=this.headingAgingBucketDescription(8);

        HeadingAgingBucketDescriptionCustomerAging2=this.headingAgingBucketDescription(9);


        HeadingCustomerAging1=this.custVendBalanceList.startdate(8);

        HeadingCustomerAging2=this.custVendBalanceList.enddate(8);


        tempHeadingCustomerAging3=this.custVendBalanceList.startdate(9);

        if(tempHeadingCustomerAging3 != Global::DateNull())

        {

            HeadingCustomerAging3=tempHeadingCustomerAging3;

        }

        HeadingCustomerAging4=this.custVendBalanceList.enddate(9);


        CustAgingReportTmp custAgingReportTmp=  next insertCustAgingReportTmp(_reverseAmountsAndHeadings);


        this.onExecuted(custAgingReportTmp,_reverseAmountsAndHeadings);

        return custAgingReportTmp;

    }


    /// <summary>

    /// 

    /// </summary>

    /// <param name = "custAgingReportTmp"></param>

    /// <param name = "_reverseAmountsAndHeadings"></param>

    public void onExecuted(CustAgingReportTmp custAgingReportTmp, boolean _reverseAmountsAndHeadings)

    {

        update_recordset custAgingReportTmp

                setting HeadingCustomerAging1=this.HeadingCustomerAging1,

            HeadingCustomerAging2=this.HeadingCustomerAging2,

            HeadingCustomerAging3=this.HeadingCustomerAging3,

            HeadingCustomerAging4=this.HeadingCustomerAging4,

            HeadingAgingBucketDescriptionCustomerAging1=this.HeadingAgingBucketDescriptionCustomerAging1,

                    HeadingAgingBucketDescriptionCustomerAging2=this.HeadingAgingBucketDescriptionCustomerAging2;

    }


    /// <summary>

    ///    Gets the heading description.

    /// </summary>

    /// <returns>

    ///    The heading text.

    /// </returns>

    [Wrappable(true)]

    public final TransTxt headingAgingBucketDescription(int HeadingNumber)

    {

        if (contract.parmAgingBuckets() && contract.parmPrintAgingBucketDescription())

        {

            return strFmt('%1', custVendBalanceList.getDescription(HeadingNumber));

        }

        else

        {

            return #emptyString;

        }

    }


}


/// <summary>

/// CustAgingReportControllerCustomerAgingExtension

/// </summary>

class CustAgingReportControllerCustomerAgingExtension extends CustAgingReportController

{

    /// <summary>

    /// construct method for CustAgingReportControllerCustomerAgingExtension class

    /// </summary>

    /// <returns></returns>

    public static CustAgingReportControllerCustomerAgingExtension construct()

    {

        return new CustAgingReportControllerCustomerAgingExtension();

    }


    /// <summary>

    /// main method

    /// </summary>

    /// <param name = "_args"></param>

    public static void main(Args _args)

    {

        SrsReportRunController formLetterController = CustAgingReportControllerCustomerAgingExtension::construct();

        CustAgingReportControllerCustomerAgingExtension controller = formLetterController;

        controller.parmReportName(ssrsReportStr(CustAgingReport_CustomerAging, DesignWithNoDetailAndNoTransactionCur));

        controller.parmArgs(_args);

        controller.startOperation();

    }


    /// <summary>

    /// getReportName method

    /// </summary>

    /// <param name = "_contract"></param>

    /// <returns></returns>

    protected str getReportName(CustAgingReportContract _contract)

    {

        str reportNameLocal;


        if (_contract.parmDetailed())

        {

            if (_contract.parmIncludeAmountCur())

            {

                reportNameLocal = ssrsReportStr(CustAgingReport_CustomerAging, DesignWithDetailAndWithTransactionCur);

            }

            else

            {

                reportNameLocal = ssrsReportStr(CustAgingReport_CustomerAging, DesignWithDetailAndNoTransactionCur);

            }

        }

        else

        {

            if (_contract.parmIncludeAmountCur())

            {

                reportNameLocal = ssrsReportStr(CustAgingReport_CustomerAging, DesignWithNoDetailAndWithTransactionCur);

            }

            else

            {

                reportNameLocal = ssrsReportStr(CustAgingReport_CustomerAging, DesignWithNoDetailAndNoTransactionCur);

            }

        }


        return reportNameLocal;

    }


}

How get primary email of customer or vendor

Below code is for customer only, for vendor we need to replace  CustTable  with VendTable.   dirPartyContactInfoView        dirPartyContactI...