前言
代码源码不重要,重要的是思想!
本工作流基于了自主研发的ORM层、数据库同步层;实现了分布式环境下的工作流协同操作。
本工作流设计遵循以下原则:
1. 工作流基于.net DataTable模型,一切围绕这个DataTable展开;因为。net在界面很多的绑定都支持了datatable。
2. 工作流模型只负责状态的维护,不负责状态的扭转。即:每天下午4点新建订单转为失效订单 这种处理不属于工作流范畴,而是属于业务调度系统,是另外一个框架。
Pixysoft.Framework.Workflow 正文
ER图:
工作流框架包括了 工作流设计对象、工作流实例对象 两大类。
1. 工作流设计对象 帮助用户自行设计一套包含表单、所有状态、状态默认扭转关系的对象。
2. 工作流实例对象 是根据用户设计好的工作流去生成实例调用。
同时说明一些设计要点:
1. WfFormSchema是表单设计对象,支持主从表的设计(就是一种自引用)
2. WfStatus是状态设计对象,包含了用户自定义的各种状态。
3. WfProjectHistory是记录工作流实例对象 状态扭转 的历史记录。
代码演示
创建一个工作流:
DataTable maintb = new DataTable("POS_ITEMDISTRIBUTION");
maintb.Columns.Add("BILLCODE");
maintb.Columns.Add("CREATEDATE");
maintb.Columns.Add("MERCHANTCODE");
maintb.Columns.Add("BOXLOCATIONCODE");
maintb.Columns.Add("USRBOXCODE");
maintb.Columns.Add("STATUS");
maintb.Columns.Add("SHOPCODE");
//新建工作流的子表单 schema
DataTable subtb = new DataTable("POS_ITEMDISTRIBUTIONDETAIL");
subtb.Columns.Add("BILLCODE");
subtb.Columns.Add("ITEMTYPENAME");
subtb.Columns.Add("INPUTPRICE");
subtb.Columns.Add("INPUTQTY");
subtb.Columns.Add("REMARK");
subtb.Columns.Add("ITEMNAME");
subtb.Columns.Add("ITEMTYPECODE");
subtb.Columns.Add("BARCODE");
subtb.Columns.Add("ISNEW");
subtb.Columns.Add("ITEMCODE");
subtb.Columns.Add("COMMISSION");
subtb.Columns.Add("STAFFCOMMISSION");
subtb.Columns.Add("ID");
//获取工作流对象
IWorkflowManager manager = WorkflowManager.Instance;
//获取设计对象
IWorkflowDesigner designer = manager.GetDesigner();
//创建一个名为POS_ITEMDISTRIBUTION的工作流(配货单)主表单为上文主表
WfProjectSchema project = designer.CreateProject("POS_ITEMDISTRIBUTION", "POS_ITEMDISTRIBUTION", "BILLCODE", maintb);
//工作流主表配置自定义搜索的关键字
designer.AddFormKeyValue(project.FormSchema, "BILLCODE");
designer.AddFormKeyValue(project.FormSchema, "MERCHANTCODE");
designer.AddFormKeyValue(project.FormSchema, "USRBOXCODE");
//根据上文schema创建工作流的子表单
WfFormSchema subform = designer.CreateSubForm(project.FormSchema, "POS_ITEMDISTRIBUTIONDETAIL", "ID", subtb);
//创建工作流的状态
WfStatus a001 = designer.CreateStartStatus(project, "NEW");
WfStatus a002 = designer.CreateNextStatus(project, a001, "CHECKED");
WfStatus a003 = designer.CreateNextStatus(project, a002, "ABNOMITY");
WfStatus a004 = designer.CreateNextStatus(project, a003, "REJECTED");
WfStatus a005 = designer.CreateNextStatus(project, a004, "PROCESSED");
WfStatus a006 = designer.CreateNextStatus(project, a005, "PASSED");
//确认设计
designer.Commit();
新建工作流实例代码:
IWorkflowManager manager = WorkflowManager.Instance;
//获取表单的对象
DataTable table = manager.GetProjectTable("POS_ITEMDISTRIBUTION");
//获取子表单对象
DataTable subtable = manager.GetProjectSubTable("POS_ITEMDISTRIBUTION");
//处理表单数据
DataRow row = table.NewRow();
row["CREATEDATE"] = DateTime.Now;
row["MERCHANTCODE"] = "123123123";
row["BOXLOCATIONCODE"] = "I0506";
row["USRBOXCODE"] = "00154";
row["STATUS"] = "NEW";
row["SHOPCODE"] = "001";
table.Rows.Add(row);
//处理子表单数据
DataRow subrow = subtable.NewRow();
subrow["INPUTPRICE"] = 100;
subrow["INPUTQTY"] = 1;
subrow["ITEMNAME"] = "hello";
subrow["ITEMTYPECODE"] = "12312";
subrow["BARCODE"] = "101540001125";
subrow["ISNEW"] = false;
subrow["ITEMCODE"] = "123123123";
subrow["COMMISSION"] = 0.02;
subrow["STAFFCOMMISSION"] = 0.02;
subtable.Rows.Add(subrow);
//根据工作流名称创建一个新的工作流
IWorkflowProject project = manager.CreateProject("POS_ITEMDISTRIBUTION");
//根据已经输入的表单创建工作流的表单
IWorkflowForm form = project.CreateForm(table);
//根据已经输入的子表单创建工作流的子表单
IWfFormCollection subforms = form.CreateSubForms(subtable);
//工作流确认
project.Commit();
工作流状态扭转:
//搜索状态为new的工作流
IWfProjectCollection projects = manager.SearchProjects("POS_ITEMDISTRIBUTION", "NEW");
if (projects.Count == 0)
return;
//工作流对象转化为Datatable
DataTable projecttb = projects.ToTable();
//获取第0行的工作流对象的datarow
DataRow projectrow = projecttb.Rows[0];
//根据datarow获取对应的工作流
IWorkflowProject project = projects[projecttb.Rows.IndexOf(projectrow)];
//状态扭转
while (project.HasNext())
{
//获取工作流的表单
IWorkflowForm form = project.GetForm();
//获取工作流表单对应的datatable
DataTable maintb = form.ToTable();
//可以自行修改表单数据 例如绑定界面等
//更新表单数据
form.Update(maintb);
//获取表单对应的子表单
IWfFormCollection subforms = form.GetSubForms();
//获取子表单对应的datatable
DataTable subformtables = subforms.ToTables();
//可以自行修改子表单数据 例如绑定界面等
//更新子表单数据
subforms.Update(subformtables);
//转移到默认下个状态
project.ToNext(null);
}
//确认操作
project.Commit();
后续
本工作流技术算是比较落后,不支持众多牛人关于扭转的算法。
个人觉得,状态扭转用代码实现是最方便的。当然,部分扭转是可以抽象成为一定的框架,例如BPEL之类的规范;变成各种时间调度、事件驱动调度等算法。但是这个如果和工作流本身的状态管理绑定在一起,就非常的不方便。
我相信用过所谓开源、0代码工作流的兄弟,一定厌倦那种xml的描述、厌倦用界面拖拖拉拉写企业代码。程序员怎么就变成了个二流的操作人员?这个是个误区,是过份夸大了xml的误区。
微软的workflow foundation是个不错的升华,重新把企业编程的权利转移给了程序员。
至于刚才所说的BPEL、时间调度算法等,我会在下一个框架实现,基于了本工作流的模型,下一个框架就叫
Pixysoft.Framework.Schedular
最后说一句,设计任何框架的目的:当然是以易用为主!