Develop Number Sequence for custom module In D365 Finance and Operations | CloudFronts

Develop Number Sequence for custom module In D365 Finance and Operations

In Finance and Operations system provide you unique number feature for new record that has been created known as Number Sequence.In most of the cases it is provided by system wherever it is necessary,and it also possible to use existing number sequence using environment only. When you create new module there you might need to setup new number sequence exclusive for that module.In such cases we might need to consider custom number sequence development,so in this blog we will see how to achieve that.
In D365 Fo number sequence development is same as that of Ax 2012 but instead of over layering we have to achieve that using extension.Following diagram will help you to get overview of development.




following are the steps which need to be performed and screenshots are also there for better understanding.

Steps:-
1.       Create an extension of NumberSeqModule Base Enum and add a new element and name it with our Module name and label as well.



2.       Now create New EDT string with the name of PayId and set its properties as follows


 3.       Now create parameter table and set its properties as follows and add key field to it


      Set its property visible as no


create new index and name it as keyIdx and add key field to it





4.       Now create another table where  number sequence is generated on its respective field of table in our case known as PayTable and field where number sequence will be applied is PayId



5.       Create new parameters form and apply table of contents pattern and add required elements(for reference you can use ProjParameters form) as follows



Now to add second tab for number sequence setup.Since number sequence is complex for beginner you can simply copy NumberSeq tab of ProjParameters form and paste in Tab form control as follows




6.     Now create form where number sequence will be implemented where PayTable will be datasource and drag its fields to form as displayed.



7. Now add the class with name of NumberSeqModulePay and extend it with NumbeSeqApplicationModule and code for that as follows :-



class NumberSeqModulePay extends NumberSeqApplicationModule
{

    /// <summary>
    /// standard method for implementing new number sequence module
    /// </summary>
    /// <returns>NumberSeqModule value</returns>
    public NumberSeqModule numberSeqModule()
    {
        return NumberSeqModule::Pay;//module name from NumberSeqModule enum extension
    }

    /// <summary>
    /// standard method for implementing new number sequence module
    /// sets up number sequences for module identifiers
    /// </summary>
    protected void loadModule()
    {
        NumberSeqDatatype datatype = NumberSeqDatatype::construct();
        datatype.parmDatatypeId(extendedTypeNum(Payid));//EDT created in previous step
        datatype.parmReferenceHelp(“Pay Id”);
        datatype.parmWizardIsContinuous(false);
        datatype.parmWizardIsManual(NoYes::No);
        datatype.parmWizardIsChangeDownAllowed(NoYes::No);
        datatype.parmWizardIsChangeUpAllowed(NoYes::No);
        datatype.parmSortField(1);
        datatype.parmWizardHighest(999999);

        datatype.addParameterType(NumberSeqParameterType::DataArea, true, false);
        this.create(datatype);

        // TODO: Add code for data types associated with the module
    }

    /// <summary>
    /// event handler for implementing new number sequence module
    /// adds the module to the global map
    /// </summary>
    /// <param name=”numberSeqModuleNamesMap”>global map for number sequence modules</param>
    [SubscribesTo(classStr(NumberSeqGlobal), delegateStr(NumberSeqGlobal, buildModulesMapDelegate))]
    public static void NumberSeqGlobal_buildModulesMapDelegate(Map numberSeqModuleNamesMap)
    {
        NumberSeqGlobal::addModuleToMap(classnum(NumberSeqModulePay), numberSeqModuleNamesMap);
    }

    public static NumberSequenceReference numRefPayId()
    {
        NumberSeqScope scope = NumberSeqScopeFactory::createDataAreaScope(curext());
        return NumberSeqReference::findReference(extendedtypenum(PayId), scope);
    }

}
this class  is used to provide number sequence setup parameters

8.       Now we need to load our number sequence to system for which create loadmodule class

code:-
class loadmodulePay
{
       public static void main(Args _args)
    {   
        NumberSeq PayNumSeq;
        PayId payid;
   
        ttsbegin;
        PayNumSeq = NumberSeq::newGetNum(NumberSeqModulePay::numRefPayId());
        payid = PayNumSeq.num();

           
        ttscommit;

        Info(strFmt(“Payslip Id  is :%1 “,payid));
    }
}


9.       Add number sequence handler to form for that add following code to PayParameter form by selecting view code option on the form this 
 
[Form]
public class PayParameters extends FormRun
{
       #ISOCountryRegionCodes

    boolean runExecuteDirect;
    TmpIdRef tmpIdRef;

    NumberSeqScope scope;
    NumberSeqApplicationModule numberSeqApplicationModule;
    container numberSequenceModules;

 

    public void init()
    {
        this.numberSeqPreInit();
        PayParameters::find();

        super();
        this.numberSeqPostInit();
    }

    void numberSeqPostInit()
    {
        numberSequenceReference_ds.object(fieldNum(NumberSequenceReference, AllowSameAs)).visible(numberSeqApplicationModule.sameAsActive());
        referenceSameAsLabel.visible(numberSeqApplicationModule.sameAsActive());
    }

    void numberSeqPreInit()
    {
        runExecuteDirect = false;

        numberSequenceModules = [NumberSeqModule::Pay];
        numberSeqApplicationModule = new NumberSeqModulePay();
        scope = NumberSeqScopeFactory::createDataAreaScope();
        NumberSeqApplicationModule::createReferences(NumberSeqModule::Pay, scope);
        tmpIdRef.setTmpData(NumberSequenceReference::configurationKeyTableMulti(numberSequenceModules));
    }

    public  NumberSeqModule numberSeqModule()
    {
        return NumberSeqModule::Pay;// module literal crated in 
NumberSeqModule enum extension previously
    }

    public Common resolveReference(FormReferenceControl _formReferenceControl)
    {
        NumberSequenceCode code = _formReferenceControl.filterValue(
                AbsoluteFieldBinding::construct(fieldStr(NumberSequenceTable, NumberSequence),
                tableStr(NumberSequenceTable))).value();

        // Do not call super as we’re providing our own disambiguation logic.
        // resolvedRecord = super(_formReferenceControl);

        return NumberSequenceTable::findByNaturalKey(code, scope.getId(true));
    }

    public Common lookupReference(FormReferenceControl _formReferenceControl)
    {
        NumberSequenceTable selectedRecord;
        SysReferenceTableLookup sysTableLookup = SysReferenceTableLookup::newParameters(tableNum(NumberSequenceTable), _formReferenceControl, true);
        Query lookupQuery;

        // Do not call super as we’re providing our own custom lookup logic.
        // selectedRecord = super(_formReferenceControl);

        // Display the Title and Department fields in the lookup form.
        sysTableLookup.addLookupfield(fieldNum(NumberSequenceTable, NumberSequence));

        // Create a custom Query that filters on NumberSequenceScope.
        lookupQuery = new Query();
        lookupQuery.addDataSource(tableNum(NumberSequenceTable)).addRange(fieldNum(NumberSequenceTable, NumberSequenceScope)).value(queryValue(scope.getId(true)));
        sysTableLookup.parmQuery(lookupQuery);

        // Return the record selected by the user.
        selectedRecord = sysTableLookup.performFormLookup();

        return selectedRecord;
    }

    [DataSource]
    class NumberSequenceReference
    {
        /// <summary>
        ///
        /// </summary>
        void removeFilter()
        {
            runExecuteDirect = false;
            numbersequenceReference_ds.executeQuery();
        }

        public display TaxBookSectionId taxBookSectionId(NumberSequenceReference _numberSequenceReference)
        {
            NumberSequenceTable numberSequenceTableLocal;

            if (numberSequenceReference.NumberSequenceId)
            {
                select firstonly NumberSequence from numberSequenceTableLocal where numberSequenceTableLocal.RecId == _numberSequenceReference.NumberSequenceId;
            }

            return TaxBookSection::findVoucherSeries(numberSequenceTableLocal.RecId).TaxBookSectionId;
        }

        void executeQuery()
        {
            if (runExecuteDirect)
            {
                super();
            }
            else
            {
                runExecuteDirect = true;
                this.queryRun(NumberSeqReference::buildQueryRunMulti(numberSequenceReference,
                                                                 tmpIdRef,
                                                                 numberSequenceTable,
                                                                 numberSequenceModules,
                                                                 scope));
                numbersequenceReference_ds.research();
            }
        }

     
        public boolean validateWrite()
        {
            boolean ret = super();

            #ISOCountryRegionCodes

            NumberSequenceDatatype numberSequenceDataType;
            NumberSequenceTable numberSequenceTableLocal;

            if (ret && SysCountryRegionCode::isLegalEntityInCountryRegion([#isoHU]))
            {
                numberSequenceDataType = NumberSequenceDatatype::find(numberSequenceReference.NumberSequenceDatatype, false);
                if (numberSequenceDataType.DatatypeId == extendedTypeNum(TaxReimbursementDoc_HU))
                {
                    numberSequenceTableLocal = numberSequenceReference.numberSequenceTable();

                    if (numberSequenceTableLocal.Manual)
                    {
                        ret = checkFailed(strFmt(“@AccountsReceivable:NumSequenceNotAllManualEdit“, “@GEE31852”));
                    }
                }
            }

            return ret;
        }

        public void init()
        {
            super();

            NumberSequenceReference_ds.cacheAddMethod(identifierStr(taxBookSectionId));
            NumberSequenceReference_ds.cacheAddMethod(tableMethodStr(NumberSequenceReference, referenceHelp));
            NumberSequenceReference_ds.cacheAddMethod(tableMethodStr(NumberSequenceReference, referenceLabel));
        }

    }
   
}

10.   Create 2 Display Menu Items for Payfrom and PayParameters and assign forms in object field of them







11.   Now create new menu and name it with Your module name and add display Menu items to it





12.   Now create extension of main menu item and add new menu reference and assign menu name with our custom menu


13.   Now finally add number Sequence handler class and other classes to Payform to use created  number sequence we have to mention field where it should be used as follows

code:-

[Form]

public class PayForm extends FormRun

{

NumberSeqFormHandler numberSeqFormHandler;

    NumberSeqFormHandler numberSeqFormHandler()
    {
        if (!numberSeqFormHandler)
        {
            numberSeqFormHandler = NumberSeqFormHandler::newForm(NumberSeqModulePay::numRefPayId().NumberSequenceId,
                                                                 element,
                                                                 PayTable_ds,
                                                                 fieldNum(PayTable, payid));
        }
        return numberSeqFormHandler;
    }
    void close()
    {
        if (numberSeqFormHandler)
        {
            numberSeqFormHandler.formMethodClose();
        }
        super();
    }
    [DataSource]
    class PayTable
    {
        /// <summary>
        ///
        /// </summary>
        /// </summary>
        public void linkActive()
        {
            element.numberSeqFormHandler().formMethodDataSourceLinkActive();
            super();
        }
        /// </summary>
        /// <returns></returns>
        public boolean validateWrite()
        {
            boolean ret;
   
            ret = super();
   
            ret = element.numberSeqFormHandler().formMethodDataSourceValidateWrite(ret) && ret;
            return ret;
        }
        /// <returns></returns>
        /// </summary>
        public void write()
        {
            ttsbegin;
            super();
            element.numberSeqFormHandler().formMethodDataSourceWrite();
            ttscommit;
        }
        public void delete()
        {
            ttsbegin;
            element.numberSeqFormHandler().formMethodDataSourceDelete();
            super();
            ttscommit;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name = “_append”></param>
        public void create(boolean _append = false)
        {
            element.numberSeqFormHandler().formMethodDataSourceCreatePre();
            super(_append);
            element.numberSeqFormHandler().formMethodDataSourceCreate(true);
        }
    }
}
14.  Now go to system administration>>number sequence and Select generate button and follow the steps which are mentioned below to generate number sequence using wizard

      Click on next button



     Again click on next button


    Now click finish button and number sequence is generated





15.   Now visit to payparameter form and click on number sequence tab and select the desired number sequence for payid field



On creating new record you can now see the number sequence is generated for payslip id (PayId)



I hope at that after referring this blog you will able to crate your own modules number sequence.

Share Story :

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close