这些天一直忙于基础BOM和生产BOM的创建和维护以及生产BOM维护流程的制定。
生产BOM是至关重要的一个文档,一方面销售对某些生产的零部件有特别的要求,在正式开工之前他们需要看生产BOM,另一方面生产BOM也要用于指导采购去采购,当然生产BOM更是指导生产领料的唯一依据。
鉴于生产BOM的重要性,把AX的生产BOM改造成适合自己需求的东西就很正常了。
1.修改 估计 逻辑
AX生产订单的估计主要是根据基础BOM得到生产产成品需要的数量。
a.对于行类型是物料的,根据基础BOM算出数量。
b.对于行类型是生产的,根据基础BOM算出数量,并生成子生产订单.
c.对于行类型是虚拟的,根据该虚拟物料的BOM组成展开.
d.对于行类型是供应商的,生成采购订单。
对于这四种类型的生产BOM行,其他的没有问题,主要是在直接生成采购订单和生产订单上的考虑,由于这个项目的基础BOM和生产BOM会有比较大的差异,在生成相应的采购订单和生产订单前用户需要做一些修改,当然AX现在的逻辑是在生成后,如果修改了生产BOM,可以再运行一次估计,这样它会自动更新与之关联的采购订单和生产订单。但是我更倾向于把生产BOM修改完成,所有相关人员都取得一致意见后再生成采购订单和生产订单,如果开始就生成了相应的采购订单,这样反反复复,各个相关部门都不知道什么时候是最终版本了。
这个修改也比较容易,找到类ProdUpdCostEstimation的costEstimateItems方法,注释掉
if (prodBOM.InventRefTransId)
this.updateSub(_prodTable,prodBOM);
else
this.createSub(_prodTable,prodBOM,inventTable);
这段代码。
当然在生产参数里加个开关是更AX的一种做法,让用户去选择是否自动生成。
然后把updateSub方法和createSub这两个方法拎出来单独做个类,在窗体上加个按钮,让用户在生产BOM确认为最终版本后,点击生成相应的采购订单和生产订单。
2.生产BOM的状态和版本控制
既然生产BOM需要各个部门协调修改,这样就应该增加一个状态来表示生产BOM是否修改完毕,修改完毕后各个部门才能根据这个最终版本的生产BOM执行各自的动作。各个部门可能生产BOM都有自己的要求,如果同时修改难免产生版本混乱的问题,还好我现在做的这个项目只有两个人会参与到生产BOM的修改,我要求以生产经理为主,在他修改完成后交由采购部门查看,如果有问题,他们两个在一起讨论修改。至于更复杂的情况,就应该有一个专门负责生产BOM维护的人,汇总各个部门的意见进行统一维护了。
3.产品信息的传递
由于产品是按单生产的,所以很多物料都是定制采购的,只用物料编码和名称以及文字描述,很难描述清楚,所以有一些图纸信息需要给供应商才能把问题说清楚。既然我们设计的是以生产BOM为中心,那么这些图纸信息显然要附加到生产BOM上,但最终还是要打印出来给供应商看,为了便于查看,需要把附加到生产BOM的图纸传递到采购订单上然后打印,要把附加到生产BOM上的文件传递到采购订单行,非常简单,只需要一行代码就可以了。
//Copy Docus
Docu::copy(_prodBOM,purchLine);
至于打印图纸给供应商,也比较简单,做一张报表,添加一个BitMap类型的字段,在打印采购订单的时候,顺便把这张报表打印出来就可以了。打印采购订单的代码在类PurchFormLetter_PurchOrder的printJournal方法,我们可以增加一个方法在打印采购订单后增加图纸报表的打印:
Code
void printJournal()
{
if (journalList.len() > 0)
{
if (printFormletter)
{
this.sendAsXML();
vendPurchOrderJour.printJournal(this, journalList);
//Farseer Begin print the images of Item
this.printItemImage();
//Farseer End
}
if (this.proforma())
{
this.removeProforma();
}
}
}printItemImage()的代码如下:
Code
/*Farseer Begin
print Item Images
Farseer End*/
void printItemImage()
{
Args parameters = new Args();
MenuFunction alxPrintItemImageMenu;
;
alxPrintItemImageMenu = new MenuFunction(menuitemoutputstr(AlxPrintItemImage),MenuItemType::Output);
parameters.parm(this.purchTable().PurchId);
alxPrintItemImageMenu.run(parameters);
}
至于报表的代码最主要的是一个fetch和display方法:
fetch方法,读取图纸记录:
Code
public boolean fetch()
{
boolean ret;
;
while select docuRef
exists join purchLine
where docuRef.RefCompanyId == purchLine.dataAreaId &&
docuRef.RefTableId == tableNum(PurchLine) &&
docuRef.RefRecId == purchLine.RecId
exists join purchTable
where purchTable.PurchId == purchLine.PurchId &&
purchTable.PurchId == element.args().parm()
{
this.send(docuRef);
}
super();
return true;
}display方法读取图纸信息,打印:
Code
display Container itemImage()
{
Container c;
BinData binData = new BinData();
;
binData.loadFile(docuRef.completeFilename());
c = binData.getData();
return c;
}
差不多就这些了,只是一个开发过程的记录,没什么技术含量,供讨论。