[AX]AX2012 Number sequence framework :(二)实现自定义模块的Number sequence

有了“[AX]AX2012 Number sequence framework :(一)概览与原理浅析”一文中对Number sequence framework的初步分析,实现自己的模块的Number sequence就比较容易理解了。这里以实现一个我们自己的“MES”模块为例来看看具体如何操作,在这个MES模块中我们有一个WeighingJobsID的EDT扩展类型,用它来表示唯一一个称量任务,它的编号来自于一个Number sequence。

1.首先我们需要在NumberSeqModule base enum下添加模块“MES”的子项

2.定义扩展类型WeighingJobId,字符串类型的EDT

3.创建保存模块参数配置的表MESParameters,可以从其他模块照抄,这个表必须有一个ParametersKey EDT类型的字段“key”,创建一个非重复的索引“Key”,仅包含字段“key”。在表MESParameters上创建一些方法:

void delete()
{
    throw error("@SYS23721");
}
void update()
{
    super();
    flush MESParameters;
}
//AOSRunMode::CalledFrom
static MESParameters find(boolean _forupdate = false)
{
    MESParameters parameter;

    parameter.selectForUpdate(_forupdate);

    select firstonly parameter
        index Key
        where parameter.Key == 0;

    if (!parameter && !parameter.isTmp())
    {
        Company::createParameter(parameter);
    }

    return parameter;
}

//返回当前Number sequence模块的ENUM值
static client server NumberSeqModule numberSeqModule()
{
    return NumberSeqModule::MES;
}

client server static NumberSequenceReference numRefWeighingJobId()
{
    
    //使用当前公司创建一个scope
    NumberSeqScope scope = NumberSeqScopeFactory::createDataAreaScope(curext());
    //根据EDT类型和scope在NumberSequenceReference表中查找相应的引用记录
    return NumberSeqReference::findReference(extendedtypenum(WeighingJobId), scope);
}

4.从NumberSeqApplicationModule扩展自己的Module类NumberSeqModuleMES,重载numberSeqModule()和loadModule()两个方法:

class NumberSeqModuleMES extends NumberSeqApplicationModule
{
}
    NumberSeqDatatype datatype = NumberSeqDatatype::construct();

    /* Weighing job number */
    //指定data type的一些参数,用于在wizard生成number sequence时使用
    datatype.parmDatatypeId(extendedTypeNum(WeighingJobId));//EDT类型
    datatype.parmReferenceHelp("Unique identifier for weighingjobs");
    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, true);//该函数可以多次调用,组合多个scope类型,注意最后一个参数,为true表示可配置 
    this.create(datatype);

  
}
public NumberSeqModule numberSeqModule()
{
   return NumberSeqModule::MES;
}

5.创建配置MES parameters的form MESParameters,其他模块照抄,删除不需要的内容,保留Data source下的表NumberSequenceReference及其下的表NumberSequenceTable,包含表MESParameters到data source,实现修改以下方法:

public class FormRun extends ObjectRun
{
    boolean                 runExecuteDirect;
    TmpIdRef                tmpIdRef;

    fieldId                 tmpFieldId;


    NumberSeqScope             scope;
    NumberSeqApplicationModule numberSeqApplicationModule;
    container                  numberSequenceModules;
}

public void init()
{
    this.numberSeqPreInit();

    super();

    MESParameters::find();

    this.numberSeqPostInit();

}
void numberSeqPreInit()
{
    runExecuteDirect   = false;

    numberSequenceModules = [NumberSeqModule::MES];
    numberSeqApplicationModule = new NumberSeqModuleMES();
    scope = NumberSeqScopeFactory::createDataAreaScope();//使用当前公司创建scope
    NumberSeqApplicationModule::createReferencesMulti(numberSequenceModules, scope);//在NumberSequenceReference表中创建当前模块的所有引用
    tmpIdRef.setTmpData(NumberSequenceReference::configurationKeyTableMulti(numberSequenceModules));
}

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

6.创建一个job调用一次NumberSeqModuleMES的loadModule()方法,注册模块的data type,当然可以放在其他一些地方来调用。loadModule()可以调用多次,它会自动更新已经创建的data type,或者添加新的data type:

static void InstallModuleMES(Args _args)
{
    NumberSeqModuleMES n = new NumberSeqModuleMES();

    n.loadModule();
}

运行一次JOB InstallModuleMES,所有我们模块的Number sequence的准备工作都做好了,接下来就可以使用“set up number sequence” wizard为我们的模块创建Number sequence,上面的例子中scope设置为按公司(DataArea),wizard会为每个公司的WeighingJobId创建一个单独的Number sequence,打开MESParameters窗口就能看到已经分配好的Number sequence。

在X++代码中我们可以这样得到一个WeighingJobId的编号:

static void TestNumSeqWeighingJobId(Args _args)
{

    ;
    ttsBegin;//如果是连续的number seuqnce,必须放在ttsbegin...ttscommit中调用
    Info(NumberSeq::newGetNum(MesParameters::numRefWeighingJobId()).num());
    ttsCommit;

}

要在form上新建纪录时自动填充WeighingJobId需要一些更多的步骤,假设有个表WeighingJobs,字段WeighingJobId使用前面的EDT类型WeighingJobId,创建form WeigingJobs使用表WeigingJobs作为数据源,在WeighingJobs form上实现以下方法:

public class FormRun extends ObjectRun
{
    NumberSeqFormHandler numberSeqFormHandler;
}
public NumberSeqFormHandler numberSeqFormHandler()
{
    if (!numberSeqFormHandler)
    {
        numberSeqFormHandler = NumberSeqFormHandler::newForm(
            MESParameters::numRefWeighingJobId().NumberSequenceId,
             element,
             WeighingJobs_ds,
             fieldnum(WeighingJobs, WeighingJobId));
    }
    return numberSeqFormHandler;
}

还需要在表WeighingJobs的data source上实现以下方法:

public void create(boolean _append = false)
{
    element.numberSeqFormHandler().formMethodDataSourceCreatePre();
    super(_append);
    element.numberSeqFormHandler().formMethodDataSourceCreate();
}
public void write()
{
    super();
    element.numberSeqFormHandler().formMethodDataSourceWrite();
}
public void delete()
{
    element.numberSeqFormHandler().formMethodDataSourceDelete();
    super();
}

做完上述工作,在form上新建一个纪录时就能为WeighingJobId字段自动分配编号了。

这里下载上述测试的样例工程,主要步骤基本上都是参照http://msdn.microsoft.com/EN-US/library/aa608474,重要的是要理解Number sequence framework是如何工作的。

原文地址:https://www.cnblogs.com/duanshuiliu/p/2703426.html