这些天一直忙于基础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;
}

差不多就这些了,只是一个开发过程的记录,没什么技术含量,供讨论。