Year in number sequence (AX2012)

I’ve noticed a lot of questions in discussion forums about how to add year to a number sequence in AX2012, e.g. to generate IDs such as 2013-xxxxx and 2014-xxxxx, that would automatically use the current year. Some people understand that number sequence scopes should allow that, but they don’t know how.

Fortunately it’s not only possible but it’s also quite simple. Rather then describing it theoretically or repeating the documentation, let’s walk through a simple end-to-end example.

Data type

First of all, we need a new data type that will be associated with the number sequence. Create a new string data type, name it DocuRevisionId, set its Label to Revision ID and StringSize to 20. The type represents a hypothetical document revision ID.

Then we need to register the type with an application module – it’ll be document management in our case. Open loadModule() method of NumberSeqModuleDocument class and add the following code at the end (I intentionally omitted everything that’s not necessary for our example):

datatype.parmDatatypeId(extendedTypeNum(DocuRevisionId));
datatype.addParameterType(NumberSeqParameterType::DataArea, true, false);
datatype.addParameterType(NumberSeqParameterType::FiscalCalendarPeriod, true, false);
this.create(datatype);

Here we’re creating a new number sequence definition for DocuRevisionId data type. We’re also defining two scope parameter types: company and fiscal calendar period. It’s very important to declare supported scope parameters – you can’t use number sequence scopes without them.

The definition has no effect unless the module is loaded. You can manage that by running the following code in a job:

new NumberSeqModuleDocument().load();

When it’s done, you can go to Organization administration > Common > Number sequences > Segment configuration and verify that our new type is there and it has both expected segments.

SegmentConfiguration

Fiscal periods

Before configuring number sequences, let’s create fiscal periods that will be used in number sequence scopes. We’ll create periods covering whole years, but you could use anything what makes sense for you.

Open General ledger > Setup > Fiscal calendars and create a new calendar – I’ll call it MyYear. It should cover the whole year:

NewFiscalCalendar

We’ll need two years for our example, therefore press the New accounting year button and create one more year (for 2014) :

AddFiscalYear

Display generated periods and set a short name for the operating period. The short name will be used automatically in number sequences, if provided. You can also rename the period in this form.

Configure fiscal period

Number sequences

Now we’ll create two number sequences – for years 2013 and 2014. They don’t have to have the same number sequence code, but they can, because the unique identifier is not the code alone, but in conjunction with a scope. We’ll use the same code because it will be needed for one additional scenario.

Go to Organization administration > Common > Number sequences > Number sequences and create a new sequence. Set fields as follows:

Number sequence code Revision
Name Revision 2013
Scope Company and Fiscal calendar period

When you choose a scope, you get additional fields – the sequence will be used only for values that you specify there. Pick your company and the operating period for year 2013 in our new calendar.

By default, the sequence includes segments for all scope parameters, therefore the format is something like DAT2013-######. Because we don’t need the company there, delete the Company segment. The value of Fiscal calendar period segment has been initialized from sequence’s short name and you can change it if needed.

We also need (at least in the typical case) to associate the sequence with a data type. Add a new item on the Reference fast tab, choose Document management area and you’ll get just a single option for Reference: Revision ID. That’s because Revision ID the only type in the selected module that supports Company and Fiscal calendar period.

The result should look like this: NewSequence

Now do the same thing once more, just use 2014 instead of 2013.

Using sequences

Everything is ready by now, we just need to have some code that will find the right number sequence and obtain a generated number.

Look at the following implementation. First of all, we find the fiscal period for a given date. Then we use it (together with the current company) to create a scope object. Finally, we find the number sequence for the given data type and scope and get a new number as usual.

date        effectiveDate = mkDate(25,05,2013);
RefRecId    calendarRecId = FiscalCalendar::findByCalendarId("MyYear").RecId;
RefRecId    periodRecId   = FiscalCalendars::findPeriodByPeriodCodeDate(calendarRecId, effectiveDate).RecId;
 
NumberSeqScope scope = NumberSeqScopeFactory::createDataAreaFiscalCalendarPeriodScope(
    curext(),
    periodRecId);
 
NumberSequenceReference seqRef = NumberSeqReference::findReference(extendedTypeNum(DocuRevisionId), scope);
 
NumberSeq::newGetNum(seqRef).num();

You should get a number like 2013-000001. If you change the year to 2014, you’ll get 2014-000001, exactly as intended. If you change the year to 2015, you’ll get an error, because no such sequence exists.

There is one more approach – it’s not normally recommended, but it’s good to know about it. We could have omitted the reference to a data type and refer to number sequences just by a common sequence code. These sequences have the same code, but they differ in scope:

SequencesReady

This source code is similar to the previous one; we just find a number sequence by its code:

date effectiveDate = mkDate(25,05,2013);
RefRecId calendarRecId = FiscalCalendar::findByCalendarId("MyYear").RecId;
RefRecId periodRecId = FiscalCalendars::findPeriodByPeriodCodeDate(calendarRecId, effectiveDate).RecId;
 
NumberSeqScope scope = NumberSeqScopeFactory::createDataAreaFiscalCalendarPeriodScope(
    curext(),
    periodRecId);
 
info(NumberSeq::newGetNumFromCode("Revision", scope).num());

Conclusion

Number sequence scopes extends abilities of number sequences in quite a straightforward way. Nevertheless if people don’t understand them properly, they often have wrong expectations. For example, they want to use Fiscal calendar period segment for a data type that doesn’t support such a scope parameter. Because the parameter is not supported, there is no code that would provide a specific value for it (for example, AX doesn’t know which date and which calendar to use).

My intention was to show all components in a single place – I hope it will help people to understand how these parts fit together.

7 Comments

  1. Hi Martin

    Thanks for the post.

    I have work a lot on number sequence by year….
    As do you know, every year for every Customer we have to setup the new Number Sequence ( Delivery Note, Invoice, etc.)
    So, I expected that the new framework help me, but pratically you have to always create a new number sequence…. and also the standard process as Invoice, Delivery Note, etc. don’t use the number sequence by Period…

    So, at the end I have modified the Number Sequence Engine and now automatically create the new Sequence when change year retrieving also the right sequence for the transactions that are related the new year or in the previous year.

    However, thanks much
    Denis

    • The frameworks allows you to do much more than changing the number of year. Maybe you want to use a completely new numbering scheme next year, to extend the length of the number and so on. The price for this flexibility is the necessity to create each individual sequence, but if it’s a problem for you, look for ways how not to do it manually.
      Where the framework helps is that you can prepare everything in advance and it will be used automatically at the right time.
      Nevertheless I agree that it doesn’t work as many people expect – that’s why they’re so confused.

      I was also surprised that it’s not used by (almost any) standard number sequence. I believe it will be used more extensively in future.

  2. Hi,

    Very useful information …thanks for the extending the information but,

    Where we need to add this code for the expected result and for existing number sequence’s whether it will work ?

    Regards,
    Rajendra S

    • Hi Rajendra,
      you can use sequences with explicit scope parameters in the same way as “normal” sequences – e.g. directly in code, in form’s NumberSeqFormHandler etc. (See Number Sequence Framework [AX 2012].)
      You may need a different way for finding the sequence, but there is no difference in how you use it.

  3. Hi Martin,

    I know this is an old post, but I am struggling to get my head around this.

    I understand how your example works for a custom field, but would it be possible to do this with a Standard AX field, like JournalNum on the LedgerJournal?

    Thanks for the great post!
    Regards,
    Tina

    • It’s not about standard and custom fields, it’s about whether the selection of a number sequence is implemented to take scope into account. You can go and change the logic, though.
      Back to your question about a specific number sequence. If I look to LedgerParameters::numRefJournalNum(), I don’t see any scope parameters provided there, therefore at least this place doesn’t support them.

  4. I recognize that this is an old post, but I would like to thank you for this post. Generating sequence numbers by fiscal year in Sales Invoices is now a legal requirements In Portugal. This saved me a few hours of work. 🙂

Comments are closed.