Trigger SalesLine update from SalesTable form header updates (price agreement)

- change date which is used in price agreement calculation
- trigger SalesLines update from SalesTable form header updates (price agreement) using Never/Always/Prompt sales ledger settings.
Settings:
Sales Ledger Parameters > Update > Update OrderLines form

Change date which is used in price agreement calculation

The method, which is used to get the date is SalesTable.getFinalDiscPriceDate()
If you need just need to extend standard dropdown and add additional value to:

Then delegates on SalesTable and SalesLine can be used:
SalesTable.finalPriceDateDelegate()
SalesLine.retrievePriceDateDelegate()
/// <summary>
/// Event handler for SalesLine /// </summary> internal final class VKSalesLineEventHandler {     /// <summary>     /// PriceDateDelegate for sales line.     /// </summary>     /// <param name = "_salesLine">sales line buffer</param>     /// <param name = "_salesPriceDateType">date type</param>     /// <param name = "_eventHandlerResult">result</param>     [SubscribesTo(tableStr(SalesLine), delegateStr(SalesLine, retrievePriceDateDelegate))]     public static void SalesLine_retrievePriceDateDelegate(SalesLine _salesLine, SalesPriceDateType _salesPriceDateType, EventHandlerResult _eventHandlerResult)     {         SalesTable          salesTable  = SalesTable::find(_salesLine.SalesId);         SalesPriceDateType  dateType    = salesTable.custTable_CustAccount().VKDateType;         if (dateType == SalesPriceDateType::VKOrderDate)         {             _eventHandlerResult.result(salesTable.VKOrderDate);         }         else if (dateType == SalesPriceDateType::VKConfirmedShipDate)         {             _eventHandlerResult.result(_salesLine.getCustDateTypePrice());         }     } }
However, if you need to consider Date type setting not only from parameters, but for example from Customers, then SalesTable.getFinalDiscPriceDate have to be overwritten:
SalesTable
/// <summary> /// Extension Class for SalesTable table. /// </summary> [ExtensionOf(tableStr(SalesTable))] final class VKSalesTableTbl_Extension {
    /// <summary>     /// COC wrapper method for getFinalDiscPriceDate     /// </summary>     /// <returns>The date for which total discount has to be calculated.</returns>     public PriceDate getFinalDiscPriceDate()     {         PriceDate priceDate;         SalesPriceDateType dateType;         SalesLine salesLine;         dateType = CustTable::find(this.CustAccount).VKDateType;         switch (dateType)         {             case SalesPriceDateType::ShippingDateRequested:                 return (select minof(ShippingDateRequested) from salesLine                             where salesLine.SalesId == this.SalesId).ShippingDateRequested;             case SalesPriceDateType::ReceiptDateRequested:                 return (select minof(ReceiptDateRequested) from salesLine                             where salesLine.SalesId == this.SalesId).ReceiptDateRequested;             case SalesPriceDateType::Today:                 return DateTimeUtil::getSystemDate(DateTimeUtil::getUserPreferredTimeZone());             case SalesPriceDateType::VKOrderDate:                 return this.VKOrderDate;             case SalesPriceDateType::VKConfirmedShipDate:                 if (this.ShippingDateConfirmed)                 {                     priceDate = this.ShippingDateConfirmed;                 }                 else                 {                     priceDate = this.ShippingDateRequested;                 }                 return priceDate;         }         return next getFinalDiscPriceDate();     }
}
SalesLine:
/// <summary> /// Extension of table SalesLine /// </summary> [ExtensionOf(tableStr(SalesLine))] final class VKSalesLineTbl_Extension {     /// <summary>     /// Extending PriceDate method using COC Wrapper     /// </summary>     /// <returns>PriceDate</returns>     public PriceDate priceDate()     {         PriceDate                   priceDate;         SalesPriceDateType          dateType;                  priceDate = next priceDate();         dateType = CustTable::find(this.CustAccount).VKDateType;         switch (dateType)         {             case SalesPriceDateType::ShippingDateRequested:                 priceDate = this.ShippingDateRequested;                 break;             case SalesPriceDateType::ReceiptDateRequested:                 priceDate = this.ReceiptDateRequested;                 break;             case SalesPriceDateType::Today:                 priceDate = DateTimeUtil::getSystemDate(DateTimeUtil::getUserPreferredTimeZone());                 break;             case SalesPriceDateType::VKOrderDate:                 priceDate = SalesTable::find(this.SalesId).VKOrderDate;                 break;             case SalesPriceDateType::VKConfirmedShipDate:                 priceDate = this.getCustDateTypePrice();                 break;         }         return  priceDate;     }     /// <summary>     /// Get price date based on shipping date     /// </summary>     /// <returns>price date</returns>     public static PriceDate getCustDateTypePrice()     { PriceDate priceDate; if (this.ShippingDateConfirmed) { priceDate = this.ShippingDateConfirmed; } else { priceDate = this.ShippingDateRequested; } return priceDate;     } }

Trigger SalesLines update from SalesTable form header updates

If the requirement is to add an additional field on the SalesTable, which should trigger update on SalesLine then you just need to add it to SalesTable.HeaderToLineUpdate field group.
New setting will appear on Sales Ledger Parameters > Update > Update OrderLines form.
You will need to implement SalesTable2LineField.lineUpdateDescriptionDelegate delegate to set description

If the requirement is to use the existing setting (from Update Order Lines form) and for example update standard Unit Price field based on the new field change:
Modification of standard AxSalesLine class behavior in order to fix standard MS issue and find the correct date using methods on the table:
/// <summary>
/// Extension of class AxSalesLine
/// </summary>
[ExtensionOf(classStr(AxSalesLine))]
final class VKAxSalesLineCls_Extension
{
    /// <summary>
    /// CoC method for initPriceDisc_PriceParamsSet
    /// </summary>
    /// <returns>PriceDisc_Price</returns>
    protected PriceDisc_Price initPriceDisc_PriceParamsSet()
    {
        // idially to place the code in CoC of setPriceDisc_PriceParams, which is called in initPriceDisc_PriceParamsSet
        // however setPriceDisc_PriceParams is private
        PriceDisc_Price priceDisc_Price = next initPriceDisc_PriceParamsSet();

        priceDisc_Price.parmPriceDate(this.salesLine().priceDate());

        return priceDisc_Price;
    }
}
SalesTable2LineUpdatePrompt class extension to trigger updates based on field modification
/// <summary>
/// Extension of class SalesTable2LineUpdatePrompt
/// </summary>
[ExtensionOf(classStr(SalesTable2LineUpdatePrompt))]
final class VKSalesTable2LineUpdatePromptCls_Extension
{
    /// <summary>
    /// CoC method for initpriceDiscUpdateTriggers()
    /// </summary>
    protected void initpriceDiscUpdateTriggers()
    {
        next initpriceDiscUpdateTriggers();

        priceDiscUpdateTriggers.add(fieldNum (SalesTable, VKOrderDate));
        priceDiscUpdateTriggers.add(fieldNum (SalesTable, ShippingDateConfirmed));
        priceDiscUpdateTriggers.add(fieldNum (SalesTable, ShippingDateRequested));
    }

    /// <summary>
    /// CoC method for initSalesTable2LineUpdateFields()
    /// </summary>
    void initSalesTable2LineUpdateFields()
    {
        next initSalesTable2LineUpdateFields();
        FieldId             fieldId = fieldNum(SalesTable, PriceGroupId);
        TableId             tableId = tableNum(SalesTable);
        SalesPriceDateType  dateType= CustTable::find(salesTable.CustAccount).VKDateType;

        if ((  (salesTable.VKOrderDate != salesTable.orig().VKOrderDate && dateType == SalesPriceDateType::VKOrderDate)
            || ((salesTable.ShippingDateConfirmed != salesTable.orig().ShippingDateConfirmed || salesTable.ShippingDateRequested != salesTable.orig().ShippingDateRequested) && dateType == SalesPriceDateType::VKConfirmedShipDate))
            // check if PriceGroupId field already changed, not to add it second time
            && !this.isFieldAlreadyInList(tableId, fieldId))
        {
            SalesTable2LineField salesTable2LineField = this.salesTable2LineFieldConstruct(tableId, fieldId);

            if (salesTable2LineField.table2LineUpdate())
            {
                salesTable2LineField.parmFieldName("@vk:RecalculateTradeAgreementsOnPriceGroup");
                if (this.updateField(salesTable2LineField))
                {
                    salesTable2LineField.updateSalesLines(NoYes::Yes);
                }
                salesTable2LineUpdateFields.addEnd(salesTable2LineField);
            }
        }
    }

    /// <summary>
    /// Identifies if the field is already in the list of salesTable2LineUpdateFields
    /// </summary>
    /// <param name = "_tableId">TableId</param>
    /// <param name = "_fieldId">FieldId</param>
    /// <returns>boolean</returns>
    boolean isFieldAlreadyInList(TableId _tableId, FieldId _fieldId)
    {
        boolean         ret;
        ListEnumerator  le = salesTable2LineUpdateFields.getEnumerator();
        while (le.movenext())
        {
            SalesTable2LineField salesTable2LineField = le.current();
            if (salesTable2LineField.tableId() == _tableId && salesTable2LineField.fieldId() == _fieldId)
            {
                ret = true;
                break;
            }
        }
        return ret;
    }

}
Extension of SalesTable2LineField if you want to change labels on the prompt dialogue:
/// <summary>
/// Extension of class SalesTable2LineField
/// </summary>
[ExtensionOf(classStr(SalesTable2LineField))]
final class VKSalesTable2LineFieldCls_Extension
{
    /// <summary>
    /// New parm method to change field name
    /// </summary>
    /// <param name = "_fieldName">FieldLabel</param>
    /// <returns>FieldLabel</returns>
    FieldLabel parmFieldName(FieldLabel _fieldName = fieldName)
    {
        fieldName = _fieldName;

        return fieldName;
    }

}
Fix to change dates if delivery dates changed together with PriceGroupId and user selects in the prompt to update them both:
/// <summary>
/// Extension of class SalesTable2LineUpdate
/// </summary>
[ExtensionOf(classStr(SalesTable2LineUpdate))]
final class VKSalesTable2LineUpdateCls_Extension
{
    /// <summary>
    /// Modifies the <c>SalesLine</c> record based on a <c>SalesTable</c> record.
    /// </summary>
    /// <param name = "_salesLine">The <c>SalesLine</c> record.</param>
    /// <param name = "_axSalesLine">The AxBC-class for the <c>SalesLine</c> record.</param>
    /// <param name = "_updateTaxGroup">Whether to update the <c>TaxGroup</c> field.</param>
    protected void modifySalesLine(SalesLine _salesLine, AxSalesLine  _axSalesLine, boolean _updateTaxGroup)
    {
        next modifySalesLine(_salesLine, _axSalesLine, _updateTaxGroup);

        // for some reason standard does not want to update delivery dates from header to lines if used checked it in prompt dialog if PriceGroupId field update is check as well
        // method AxSalesLine.shouldUpdateSalesLineDlvDateFromHeader:
        //        return !(_dlvDate
        //  && this.axSalesTable().isFieldModified(fieldNum(SalesTable, PriceGroupId)));
        // however it should be desided by prompt selection, not like that

        if (this.isFieldInUpdateList(tableNum(SalesTable), fieldNum(SalesTable, DeliveryDate)))
        {
            _axSalesLine.parmShippingDateConfirmed(SalesTable.ShippingDateConfirmed);
            _axSalesLine.parmShippingDateRequested(SalesTable.ShippingDateRequested);
            _axSalesLine.parmReceiptDateConfirmed(SalesTable.ReceiptDateConfirmed);
            _axSalesLine.parmReceiptDateRequested(SalesTable.ReceiptDateRequested);
        }
    }

    /// <summary>
    /// Identifies if the field is already in the list of salesTable2LineUpdateFields
    /// </summary>
    /// <param name = "_tableId">TableId</param>
    /// <param name = "_fieldId">FieldId</param>
    /// <returns>boolean</returns>
    boolean isFieldInUpdateList(TableId _tableId, FieldId _fieldId)
    {
        boolean         ret;
        ListEnumerator  le = salesTable2LineUpdateFields.getEnumerator();
        while (le.movenext())
        {
            SalesTable2LineField salesTable2LineField = le.current();
            if (salesTable2LineField.tableId() == _tableId && salesTable2LineField.fieldId() == _fieldId)
            {
                ret = true;
                break;
            }
        }
        return ret;
    }

}
Prompt dialog looks like:


 

Search

About

DaxOnline.org is free platform that allows you to quickly store and reuse snippets, notes, articles related to Dynamics AX.

Authors are allowed to set their own AdSense units and "buy me a coffee" link.
Join us.

Blog Tags