插件开发技术说明(15)---单据处理编程模式

以CSale为例说明.

1.定义单据类

包括主表类和明细类.

#include "RecordsetBinder.h" ///< BIND_DECLARE,...
class CSale:public CSheet{
public:
	CSale():CSheet(2050) {
	}
	CSale(SLIC_SHEETID sheet_id):CSheet(2050,sheet_id) {
	}
public:
	static int Init();
	BIND_DECLARE(CSale)
};
.单据类实现2个构造函数.***注意要初始化单据类成员变量.上述代码略.
.增加BIND_DECLARE(CSale),宏BIND_DECLARE定义与绑定有关的静态成员和方法.
.单据类实现文件中声明变量,字段绑定信息初始化.

CRecordsetBindObject<CSale> CSale::binder_;
CRecordsetBindObject<CSale::CSaleDetail> CSale::CSaleDetail::binder_;
/
CFieldBind CSale::fld_bind_[] = {
	FIELD_BIND3(CSale,sheet_id_,"SheetID",true),
	FIELD_BIND1(CSale,eid_,"EId"),
	FIELD_BIND1(CSale,co_eid_,"CoEId"),
	FIELD_BIND1(CSale,ref_sheet_id_,"RefSheetId"),
	FIELD_BIND1(CSale,user_id_,"UserId"),
	FIELD_BIND1(CSale,stock_id_,"StockId"),
	FIELD_BIND1(CSale,group_id_,"GroupId"),
	FIELD_BIND1(CSale,dept_id_,"DeptId"),
	FIELD_BIND1(CSale,send_type_,"SendType"),
	FIELD_BIND1(CSale,disc_value_,"DiscValue"),
	FIELD_BIND1(CSale,crm_value_,"CrmValue"),
	FIELD_BIND1(CSale,pay_type_,"PayType"),
	FIELD_BIND1(CSale,pur_flag_,"PurFlag"),
	FIELD_BIND1(CSale,pur_value_,"PurValue"),
	FIELD_BIND1(CSale,delivery_date_,"DeliveryDate"),
	FIELD_BIND1(CSale,delivery_address_,"DeliveryAddress"),
	FIELD_BIND1(CSale,contact_,"Contact"),
	FIELD_BIND1(CSale,contact_mobile_,"ContactMobile"),
	FIELD_BIND1(CSale,notes_,"Notes"),
	FIELD_BIND1(CSale,status_,"Status"),
	FIELD_BIND1(CSale,del_flag_,"DelFlag"),
	FIELD_BIND1(CSale,operator_,"Operator"),
	FIELD_BIND1(CSale,creator_,"EditOr"),
	FIELD_BIND1(CSale,create_time_,"EditDate"),
	FIELD_BIND1(CSale,from_id_,"FromId"),
};

CFieldBind CSale::CSaleDetail::fld_bind_[] = {
	FIELD_BIND1(CSale::CSaleDetail,eid_,"EId"),
	FIELD_BIND1(CSale::CSaleDetail,sheet_id_,"SheetID"),
	FIELD_BIND1(CSale::CSaleDetail,line_num_,"LineNum"),
	FIELD_BIND1(CSale::CSaleDetail,goods_id_,"GoodsId"),
	FIELD_BIND1(CSale::CSaleDetail,barcode_,"Barcode"),
	FIELD_BIND1(CSale::CSaleDetail,stype_,"SType"),
	FIELD_BIND1(CSale::CSaleDetail,icolor_,"IColor"),
	FIELD_BIND1(CSale::CSaleDetail,isize_,"ISize"),
	FIELD_BIND1(CSale::CSaleDetail,wp_rate_,"WPRate"),
	FIELD_BIND1(CSale::CSaleDetail,cost_,"Cost"),
	FIELD_BIND1(CSale::CSaleDetail,tax_rate_,"TaxRate"),
	FIELD_BIND1(CSale::CSaleDetail,bulk_price_,"BulkPrice"),
	FIELD_BIND1(CSale::CSaleDetail,pack_price_,"PackPrice"),
	FIELD_BIND1(CSale::CSaleDetail,old_bulk_price_,"OldBulkPrice"),
	FIELD_BIND1(CSale::CSaleDetail,old_bulk_price_,"OldBulkPrice"),
	FIELD_BIND1(CSale::CSaleDetail,bulk_qty_,"BulkQty"),
	FIELD_BIND1(CSale::CSaleDetail,pack_qty_,"PackQty"),
	FIELD_BIND1(CSale::CSaleDetail,pack_unit_qty_,"PackUnitQty"),
	FIELD_BIND1(CSale::CSaleDetail,promotion_sheetid_,"PromotionSheetID"),
	FIELD_BIND1(CSale::CSaleDetail,prefer_notes_,"PreferNotes"),
	FIELD_BIND1(CSale::CSaleDetail,disc_value_,"DiscValue"),
	FIELD_BIND1(CSale::CSaleDetail,gift_qty_,"GiftQty"),
	FIELD_BIND1(CSale::CSaleDetail,gift_flag_,"GiftFlag"),
	FIELD_BIND1(CSale::CSaleDetail,stk_qty_,"StkQty"),
	FIELD_BIND1(CSale::CSaleDetail,notes_,"Notes"),
};

/
int CSale::Init() {
	ISheetTypeInfo *sti = CDataEnv::env_->sheet_type_mgr_->Add(2050,"t_ven_sale","t_ven_saleitem",0);

	binder_.SetFieldBindInfo(&fld_bind_[0],sizeof(fld_bind_)/sizeof(fld_bind_[0]),false);
	CSale::CSaleDetail::binder_.SetFieldBindInfo(&CSale::CSaleDetail::fld_bind_[0],sizeof(CSale::CSaleDetail::fld_bind_)/sizeof(CSale::CSaleDetail::fld_bind_[0]),false);

	sti->SetBinder(&binder_,&CSale::CSaleDetail::binder_,0);

	return 0;
}

CSale::Init()在插件的Initialize函数中调用.

int CSd::Initialize() {
  parent::Initialize();
	CSale::Init();
  return 0;
}

如果需要,重载基类的函数:
如校验单据数据有效性.对明细进行合计.

public:
    void AddDetail(CSheetDetail *pDetail,short index=0);
		int Check();

实现:

/
int CSale::Check() {
	return this->pur_value_ >= this->disc_value_;
}
/
void CSale::AddDetail(CSheetDetail *pDetail,short index) {
	CSale::CSaleDetail *detail = (CSale::CSaleDetail*)pDetail;
  detail->sale_ = this;
  detail->line_num_ = details_.size()+1;
  this->pur_value_ += detail->bulk_qty_*detail->bulk_price_;
  this->pur_value_ += detail->pack_qty_*detail->pack_price_;
  this->pack_qty_ += detail->pack_qty_;
  details_[index]->push_back(detail);
}

这样定义后,就具有了许多常用的功能.无需增加其它代码.

2.使用示例


2.1插入新单据

以下是iep_b处理EVENT_NEW_PURCHASE事件的代码.

EVENT_NEW_PURCHASE在slic_event.h中定义.

#define EVENT_NEW_PURCHASE			7800	/// 采购订单
代码:

int CIEPB::OnNewPurchase(CEvent *e) {
	vector<string> vs;
	CHECK_EVENT_REFER(e,vs,2,-1); ///< 事件主体
	unsigned int eid = atol(vs[0].c_str());
	unsigned __int64 sheet_id = _atoi64(vs[1].c_str());
	vector<string> vs2;
	CHECK_EVENT_PARA(e,vs2,1,-1); ///< 事件参数
	unsigned int co_eid = atol(vs2[0].c_str());

	mpm_ns::CPurchase purchase;
	int ret = purchase.Load(sheet_id); ///< 读入采购订单信息
	if (ret!=1)
		return ret;

	sd_ns::CSale sale;
	Purchase2Sale(purchase,sale); ///< 采购订单转销售单

	if (sale.ApplyID())
		return -1;
	if (sale.Insert()) ///< 插入订单
		return -1;

	return 0;
}

sale.Insert调用的是CSheet的方法,不需要再对CSale编写代码.


2.2读入单据

读入指定的单据.
以下代码中的sale.Load加载整张单据,而用sale.Select则可以读所需的字段,减少开销.


下列代码是iep_b插件处理销售单状态改变的代码


int CIEPB::OnSaleStatusChanged(unsigned __int64 sheet_id,int status) {
	sd_ns::CSale sale;
	sale.sheet_id_ = sheet_id;
	int ret = sale.Select("purflag","refsheetid","fromid",0); ///< 仅读取所需要的字段
//	int ret = sale.Load(sheet_id); ///< 加载整张单据
	if (ret==-1)
		return -1;
	if (ret==0) {/// ==0无此单据
		return 0;
	}

	if (sale.ref_sheet_id_==0) ///< 
		return 0;
	if (sale.pur_flag_==0) {
		COrder order;
		order.sheet_id_ = sale.ref_sheet_id_;
		if (order.UpdateStatus(status))
			return -1;
		
	}
	else if (sale.pur_flag_==1) {
		CPurchase purchase;
		purchase.sheet_id_ = sale.ref_sheet_id_;
		if (purchase.UpdateStatus(status))
			return -1;
	}

	return 1;
}

3.优化内容

。对象与字段绑定:可大幅降低代码量,并降低开销,提高处理性能
(1)统一字段映射:
此前CRecordsetBindObject和ITableHandler分别执行绑定,分别对应查询和插入/修改/更新操作.
查询时,         

    CRecordsetBindObject<CSale> binder;
    binder.BindRecordset(prs);
    binder.BindField(NEW_FIELD_BIND(CSale,ORM_FIELD_TYPE_ULONG,0,eid_,"EId"));

插入/修改/更新时:               
    ITableHandler *th = CDataEnv::env_->db_helper_->NewTableHandler(pdbor,"t_Ven_SaleItem");
    AUTO_POINTER_NODECLARE(ITableHandler,th);
    th->BindField("Eid",(char**)&this->eid_,sizeof(this->eid_));    
(2)预绑定:不需要再运行时每次进行绑定,减少cpu开销,提高处理速度    


。支持一主多从表:更复杂的结构以后扩展支持
。扩展单据基类CSheet,大幅降低单据业务处理的编程量,提高开发效率.
***已有的业务单据类实现若直接应用,可删除大量的代码.


此模式可进一步延伸到非单据类,初步思路:
orm_helper.h中定义CORM类,承接CSheet中的若干功能.非单据类从CORM派生。


3.附:相关实现代码


3.1CSheet虚函数

		virtual CRecordsetBindObjectBase* GetBinder() { return 0; }
		virtual CRecordsetBindObjectBase* NewBinder(const char *fld,...) { return 0; }
		virtual CRecordsetBindObjectBase* NewBinder(const char *fld,va_list arg) { return 0; }
		///< 检查对象数据是否有效
		///< @return -1:错误 0:无效 1:有效
		virtual int Check() { return 1; }


        virtual int ApplyID(); ///< 生成单据编号


		/// @return 0-成功 -1-失败 1-存在主键冲突
		virtual int Insert(short on_dup_error=2); ///< on_dup_error 忽略-1,按错误处理-2,更新-3 
		virtual int Update(short inc_detail); ///< 修改单据 inc_detail:是否更新明细
		virtual int Update(const char *fld,...); ///< 修改指定的单据字段
		virtual int Select(const char *fld,...); ///< 查询指定的单据字段
		virtual int Delete(); ///< 删除单据
		virtual int DeleteDetail(); ///< 删除明细
		virtual void ClearDetail(short index=0);
		virtual void ClearAllDetail();


		virtual void AddDetail(CSheetDetail *pDetail,short index=0);
		virtual int Load(SLIC_SHEETID sheet_id,bool load_detail=true); ///< 加载单据信息
		virtual int LoadDetail(); ///< 加载明细信息


    virtual int Save(); ///< 保存单据
    virtual int UpdateStatus(int nStatus);


其中,Save是兼容性保留,待废弃. 

int Update(const char *fld,...)暂未实现.    
  


3.2BIND_DECLARE宏

 #define BIND_DECLARE(CLS) \
	static CFieldBind fld_bind_[];\
	static CRecordsetBindObject<CLS> binder_; \
	CRecordsetBindObjectBase* GetBinder() { return &binder_; }\
	CRecordsetBindObjectBase* NewBinder(const char *fld,va_list arg) { \
		CRecordsetBindObject<CLS>  *binder = new CRecordsetBindObject<CLS> ; \
		const char *p = fld;\
		while(p) { \
			CFieldBind* f = binder_.GetField(p); \
			binder->BindField(f); \
			p = va_arg(arg,const char *); \
		} \
		return binder; \
	}\
	CRecordsetBindObjectBase* NewBinder(const char *fld,...) { \
	va_list vl;\
	va_start(vl,fld);\
	CRecordsetBindObjectBase  *binder = NewBinder(fld,vl);\
	return binder;\
	}\       




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值