有了“[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是如何工作的。