wms接口开发说明

  

1   概述

zdb平台与第三方平台对接的一个范例。

基于sealink wms定义的接口实现。

接口技术要求简述如下:

l  http协议

l  消息body采用json格式

l  通过url传递系统参数

 

zdb端实现上行部分的接口(WTE),2个平台之间彼此调用,实现业务流程的衔接。

 

本文用采购进货和验收确认为例描述具体的代码实现。

 

2   接口

作为开发示例的2个接口定义如下。

2.1    进货通知(ETW_PURCHASE)

zdb在采购订单审核后调用。

 

请求参数

名称

类型

是否必须

示例值

更多限制

描述

sheetid

String

 

 

 

warehouse_no

String

 

 

仓库编码

owner_no

String

123

 

货主编码

org_no

String

 

 

机构代码

venderid

String

 

 

进货供货商编码

purchase_no

String

 

 

采购单号

sdate

Date

 

 

采购单审核日期

checker

String

 

 

制单员姓名

class_type

String

 

 

类型

purdate

Date

 

 

送货日期

validdate

Date

 

 

有效日期

notes

String

 

 

订单说明

orderlist

Purchase[]

 

 

 

serialid

Number

 

 

单内序号

owner_article_no

String

 

 

商品编码

pkcount

Number

 

 

订货规格

qty

Number

 

 

进货总量

owner_cust_no

String

 

 

客户代码

cust_qty

Number

 

 

客户要货量

cust_po_no

String

 

 

客户订单号

cust_note

String

 

 

客户备注

 

响应参数

名称

类型

示例值

描述

flag

String

success

 

code

String

000

返回状态码

message

String

 

返回状态描述

 

 

2.2    验收确认(WTE_IM_CHECK)

wms调用。

请求参数

名称

类型

是否必须

示例值

更多限制

描述

sheetid

String

 

 

传单单据编号

warehouse_no

String

 

 

仓库编码

owner_no

String

123

 

货主编码

po_no

String

 

 

进货通知单号

checkno

String

 

 

验收单号

supplier_no

String

 

 

供货商编码

sdate

Date

 

 

验收时间

orderlist

Purchase[]

 

 

 

serialid

Number

 

 

单内序号

owner_article_no

String

 

 

商品编码

prodate

Date

 

 

生产日期

qty

Number

 

 

验收总量

 

响应参数

名称

类型

示例值

描述

flag

String

success

 

code

String

000

返回状态码

message

String

 

返回状态描述

 

3   实现

ETW接口实现在client,WTE接口实现在server模块中。

3.1    进货通知(ETW_PURCHASE)

3.1.1    请求定义

根据接口定义文档定义请求业务对象和请求传输请求体对象。

 

请求业务对象类型:

///< 进货通知单

struct CPurchase {

       string sheetid_;/// 传单单据编号   

       string warehouse_no_;/// 仓库编码

       string owner_no_;/// 货主编码     

       string org_no_; /// 机构代码

       string venderid_; /// 进货供货商编码

       string purchase_no_;/// 采购单号 

       string sdate_; /// 采购单审核日期 

       string checker_;/// 制单员姓名     

       string class_type_;/// 类型    

       string purdate_; /// 送货日期

       string validdate_;///有效日期

       string notes_;/// 订单说明    

       struct CItem { ///< 商品明细

              int serialid_;///单内序号

              string owner_article_no_;

             int pkcount_; ///< 订货规格

              double qty_; ///     进货总量

              string owner_cust_no_;/// 客户代码     

              double cust_qty_;///客户要货量    

              string cust_po_no_;/// 客户订单号

              string cust_note_; /// 客户备注    

              CItem():serialid_(0),qty_(0),cust_qty_(0),pkcount_(1) {

              }

              MEMBER_DEFINE(CItem);

              int Load(mpm_ns::CPurchase::CPurchaseDetail &item);

       };

       CAutoVector<CItem*> items_; ///< 商品明细

 

       CPurchase() {

              org_no_ = ORG_NO;

              class_type_ = "0";

       }

 

       MEMBER_DEFINE(CPurchase);

       int Load(mpm_ns::CPurchase &purchase);

};

 

请求体类型:

///< 进货通知单请求体

struct CPurchaseRequestBody : public CMasterSlaveRequestBody<CPurchase,CPurchase::CItem> {

       MEMBER_DEFINE(CPurchaseRequestBody);

 

       CPurchaseRequestBody():CMasterSlaveRequestBody("orderlist") {

              method_ = "ETW_PURCHASE";

       }

};

 

CMasterSlaveRequestBody为主从结构类型的请求体,模板参数CPurchase为请求业务对象类型,CPurchase::CItem为明细类型。

orderlist为明细数组名称。

ETW_PURCHASE为方法名称。

 

3.1.2    请求与消息绑定

绑定建立json消息与对象成员之间的映射。

SET_MEMBER_BEGIN(CPurchase)

       SET_MEMBER2(CPurchase,sheetid_,"sheetid",false),

       SET_MEMBER2(CPurchase,warehouse_no_,"warehouse_no",false),

       SET_MEMBER2(CPurchase,owner_no_,"owner_no",false),

       SET_MEMBER2(CPurchase,org_no_,"org_no",false),

       SET_MEMBER2(CPurchase,venderid_,"venderid",false),

       SET_MEMBER2(CPurchase,purchase_no_,"purchase_no",false),

       SET_MEMBER2(CPurchase,sdate_,"sdate",false),

       SET_MEMBER2(CPurchase,checker_,"checker",true),

       SET_MEMBER2(CPurchase,class_type_,"class_type",false),

       SET_MEMBER2(CPurchase,purdate_,"purdate",false),

       SET_MEMBER2(CPurchase,validdate_,"validdate",true),

       SET_MEMBER2(CPurchase,notes_,"notes",true),

       SET_MEMBER2(CPurchase,purdate_,"purdate",false),

       SET_MEMBER2(CPurchase,validdate_,"validdate",true),

SET_MEMBER_END(CPurchase)

 

SET_MEMBER_BEGIN(CPurchase::CItem)

       SET_MEMBER2(CPurchase::CItem,serialid_,"serialid",false),

       SET_MEMBER2(CPurchase::CItem,owner_article_no_,"owner_article_no",false),

       SET_MEMBER2(CPurchase::CItem,pkcount_,"pkcount",true),

       SET_MEMBER2(CPurchase::CItem,qty_,"qty",false),

       SET_MEMBER2(CPurchase::CItem,owner_cust_no_,"owner_cust_no",true),

       SET_MEMBER2(CPurchase::CItem,cust_qty_,"cust_qty",true),

       SET_MEMBER2(CPurchase::CItem,cust_po_no_,"cust_po_no",true),

       SET_MEMBER2(CPurchase::CItem,cust_note_,"cust_note",true),

SET_MEMBER_END(CPurchase::CItem)

 

SET_MEMBER2的3个参数含义分别如下:成员变量名称,接口参数名称,是否允许空。

 

3.1.3    接口转换

接口转换把业务对象转换为请求对象。

本步骤基于业务相关设计人员对接口转换规则明确描述后进行。

业务对象是zdb系统内部描述业务的对象,请求对象为接口定义的用于接口之间的调用的对象。

本接口的业务对象类型为mpm_ns::CPurchase,转换为上面定义的CPurchase类型,包括明细类型转换。

下行转换方法为Load,上行转换方法为Output。

 

业务对象转换为请求对象

int CPurchase::Load(mpm_ns::CPurchase &purchase) {

       GET_SHARDINGID(purchase.eid_,_inner_env_->sharding_id_,-1);

       this->sheetid_ = GetSheetId();

       this->warehouse_no_ = LogMsg("%d",purchase.stock_id_);

       this->owner_no_ = LogMsg("%d",purchase.eid_);

       this->org_no_ = ORG_NO;

       this->venderid_ = LogMsg("%d",purchase.co_eid_);

       this->purchase_no_ = GET_UNIQUE_SHEETID(_inner_env_->sharding_id_,purchase.sheet_id_);

       this->sdate_ = purchase.check_date_;

       this->checker_ = purchase.checker_;

       this->class_type_ = "0";

       this->purdate_ = purchase.delivery_date_;

       this->notes_ = purchase.notes_;

 

       if (purchase.details_.size()==0)

              return 0;

       vector<CSheetDetail*>::iterator iter = purchase.details_[0]->begin();

       while(iter!=purchase.details_[0]->end()) {

              mpm_ns::CPurchase::CPurchaseDetail *detail = (mpm_ns::CPurchase::CPurchaseDetail*)*iter;

              CPurchase::CItem *item = new CPurchase::CItem;

              item->Load(*detail);

              this->items_.push_back(item);

              iter++;

       }

 

       return 0;

}

 

此方法从业务对象(mpm_ns::CPurchase类型)生成对应的请求对象数据。

GET_UNIQUE_SHEETID用于生成唯一单据编号,由于单据编号在zdb各分区主站内唯一,但全局不唯一,因此由分区id和原始单据编号拼接而成,分区id占起始4个字符。

上行确认时需要反向操作,拆分出分区id和原始单据编号。

 

明细类型转换

int CPurchase::CItem::Load(mpm_ns::CPurchase::CPurchaseDetail &item) {

       this->serialid_ = item.line_num_;

       this->owner_article_no_ = LogMsg("%lu",item.goods_id_);

       this->pkcount_ = item.pack_unit_qty_;

       this->qty_ = item.bulk_qty_ + item.pack_qty_*item.pack_unit_qty_;

       this->cust_note_ = item.notes_;

 

       return 0;

}

 

3.1.4    增加事件处理函数

在插件头文件中声明采购订单审核事件函数,并实现。

int CSealinkWMS::OnNewPurchase(CEvent *e) {

       return HandleMasterSlave<mpm_ns::CPurchase,CPurchaseRequestBody>(e,"OnNewPurchase");

}

 

3.1.5    登记事件

在event_handle_map中增加事件响应函数项。

CEventHandleMapItem event_handle_map[] = {

       {EVENT_NEW_PURCHASE,(EventHandleFunc)&CSealinkWMS::OnNewPurchase},///<进货通知

};

 

EVENT_NEW_PURCHASE是在采购订单审核后由业务系统激发,由wms接口的事件代理捕获,执行上面注册的函数CSealinkWMS::OnNewPurchase。

 

3.2    验收确认(WTE_IM_CHECK)

3.2.1    请求定义

根据接口定义文档定义请求业务对象和请求传输请求体对象。

 

请求业务对象类型:

///< 验收(进货)确认单

struct CPurchaseAck : public CAckBase {

    string sheetid_;/// 传单单据编号 STRING(20) 不允许 

    string warehouse_no_;/// 仓库编码    STRING(3)  不允许 仓库编码

    string po_no_; /// 进货通知单号  STRING(20) 不允许 进货通知单号

    string checkno_; /// 验收单号    STRING(20) 不允许 WMS验收单单号)

    string supplier_no_; /// 供货商编码  STRING(10) 不允许 进货供货商编码

    string sdate_;/// 验收时间   date       日期格式:2008-10-11

 

    struct CItem {

        int serialid_;///单内序号    NUMBER 不允许 采购单内序号

        string owner_article_no_;/// 商品编码    STRING(20) 不允许 

        double qty_; /// 验收总量    Decimal(12,3)

        string prodate_;/// 生产日期 date   允许

        CItem():qty_(0),serialid_(1) {

        }

        MEMBER_DEFINE(CItem);

        int Output(gsm_ns::CStorage::CStorageDetail &item);

    };

 

    CAutoVector<CItem*> items_;

 

    CPurchaseAck() {

    }

    MEMBER_DEFINE(CPurchaseAck);

    int Output(gsm_ns::CStorage &storage);

};

 

这里只实现Output方法,把请求业务对象转换为系统业务对象。

 

请求体类型:

///< 进货确认单请求体

struct CPurchaseAckRequestBody : public CMasterSlaveRequestBody<CPurchaseAck,CPurchaseAck::CItem> {

    MEMBER_DEFINE(CPurchaseAckRequestBody);

 

    CPurchaseAckRequestBody():CMasterSlaveRequestBody("orderlist") {

        method_ = "WTE_IM_CHECK";

    }

};

CMasterSlaveRequestBody为主从结构类型的请求体,模板参数CPurchaseAck为请求业务对象类型,CPurchaseAck::CItem为明细类型。

orderlist为明细数组名称。

WTE_IM_CHECK为方法名称。

 

3.2.2    请求与消息绑定

绑定建立json消息与对象成员之间的映射。

SET_MEMBER_BEGIN(CPurchaseAck)

    SET_MEMBER2(CPurchaseAck,sheetid_,"sheetid",false),

    SET_MEMBER2(CPurchaseAck,warehouse_no_,"warehouse_no",false),

    SET_MEMBER2(CPurchaseAck,owner_no_,"owner_no",false),

    SET_MEMBER2(CPurchaseAck,po_no_,"po_no",false),

    SET_MEMBER2(CPurchaseAck,checkno_,"checkno",false),

    SET_MEMBER2(CPurchaseAck,supplier_no_,"supplier_no",false),

    SET_MEMBER2(CPurchaseAck,sdate_,"sdate",true),

SET_MEMBER_END(CPurchaseAck)

 

SET_MEMBER_BEGIN(CPurchaseAck::CItem)

    SET_MEMBER2(CPurchaseAck::CItem,owner_article_no_,"owner_article_no",false),

    SET_MEMBER2(CPurchaseAck::CItem,prodate_,"prodate_",true),

    SET_MEMBER2(CPurchaseAck::CItem,qty_,"qty",false),

    SET_MEMBER2(CPurchaseAck::CItem,serialid_,"serialid",false),

SET_MEMBER_END(CPurchaseAck::CItem)

 

3.2.3    接口转换

把请求对象转换为业务对象。

int CPurchaseAck::Output(gsm_ns::CStorage &storage) {

    storage.eid_ = atoi(this->owner_no_.c_str());

    string dbc_name;

    if (PinDB(dbc_name))

        return -1;

    storage.dbc_name_ = dbc_name;

 

    storage.stock_id_ = atoi(this->warehouse_no_.c_str());

    SEPARATE_SHEETID(this->po_no_,storage.ref_sheet_id_,-1);

    storage.co_eid_ = atoi(this->supplier_no_.c_str());

    storage.check_date_ = this->sdate_;

    storage.notes_ = ACK_NOTES_TEXT;

    storage.creator_ = ACK_USER;

    storage.oper_date_ = CDateTime::Now().GetDateTime();

 

    if (this->items_.size()==0)

        return 0;

 

    vector<CPurchaseAck::CItem*>::iterator iter = items_.begin();

    while(iter!=items_.end()) {

        CPurchaseAck::CItem *item = *iter;

        gsm_ns::CStorage::CStorageDetail *detail =  new gsm_ns::CStorage::CStorageDetail;

        if (item->Output(*detail))

            return -1;

        storage.details_[0]->push_back(detail);

        iter++;

    }

 

    return 0;

}

 

PinDB根据请求对象内容的货主,确定数据库分区并存储在TLS中,获取数据库连接名。

SEPARATE_SHEETID从请求对象的单据编号,分离出原始单据编号。

3.2.4    增加响应函数

int CSealinkWMS::OnPurchaseAck(string &request,CResponseBodyBase **response) {

       CPurchaseAckRequestBody req;

       return req.Handle<gsm_ns::CStorage >(request, SDT_PURCHASE,6049);

}

 

request为请求的消息体(json)内容.

这里Handle调用的含义是对采购确认生成入库单(gsm_ns::CStorage类型),SDT_PURCHASE为入库类型,入库后自动审核,审核采用6049协议。

 

3.2.5    登记接口

在GetHandleFunc函数的func_maps中增加响应函数入口项:

HandleRequestFuncPtr GetHandleFunc(string &method) {

       static struct CFuncMap {

              string method_;

              HandleRequestFuncPtr func_ptr_;

       } func_maps[] = {

              {"WTE_IM_CHECK",&CSealinkWMS::OnPurchaseAck},///<验收(进货)确认

       };

       for (unsignedint i=0;i<sizeof(func_maps)/sizeof(func_maps[0]);i++) {

              CFuncMap &item = func_maps[i];

              if (stricmp(item.method_.c_str(),method.c_str())==0)

                     return item.func_ptr_;

       }

       return 0;

}

 

 

 

4   后记

基于一份有映射关系的接口文档开发,根据接口文档声明类型;根据业务数据映射规则进行成员赋值。

 

所采用的实现已经尽可能简化了。

基于此方法开发,工作量容易评估,bug率及重复率低,维护扩展容易。

如增加一参数,基本就增加一个变量,绑定一下,映射一下,共3行代码就可以解决。

若接口支持xml,这些代码无需任何变动。

 

理论上,再简化还有2个方向:

l  应用无关:不涉及业务对象,这是不同的抽象级别,完全是另一种实现

l  代码生成工具:程序就是取代人做重复的程序化的事情的,基于接口描述生成上面的代码主干再修改。

工具的价值取决于重复使用量,低价值的工具不值得开发。

 

本文就如何进行此类开发进行演示说明,背后的支撑是广泛的,不在此赘言。

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: SAP和WMS是两种不同的软件系统,它们可以通过接口进行集成和开发。 SAP是ERP(企业资源计划)软件的代表,可用于管理企业的核心业务流程,如采购、生产、销售和物流等。WMS是仓库管理系统,用于优化和管理仓库内的物流流程。通过将这两个系统集成在一起,企业可以更好地管理其供应链和仓库操作。 接口开发是将不同系统之间的数据和功能进行集成的过程。在SAP和WMS接口开发中,需要确保两个系统之间的数据传输和信息共享的平稳进行。 首先,我们需要定义接口的功能和数据需求。这包括在SAP和WMS之间传输的数据对象、数据格式、数据字段等。 然后,我们可以使用适合的技术来实现接口开发。例如,可以使用SAP的IDoc技术或Web服务来传输数据。在WMS系统中,可能需要编写相关的接收和处理数据的逻辑代码。 在开发接口之前,我们还需要进行系统间的配置和对接。这包括在SAP中配置相应的数据导出和导入程序,以及在WMS中配置数据接收和处理的功能。 最后,我们需要进行接口的测试和调试。这可以确保数据的准确性和完整性,以及接口的稳定性和可靠性。 总之,SAP和WMS接口开发是将两个系统集成的关键步骤。通过合理的功能定义、技术选择、系统配置和测试调试,我们可以实现两个系统之间的顺畅数据传输和信息共享,从而提高企业的供应链管理和仓库运营效率。 ### 回答2: SAP是一种企业资源规划系统,WMS是仓库管理系统,它们之间的接口开发是为了实现数据的互通和共享。 SAP和WMS之间的接口开发需要根据实际业务需求和系统架构进行设计和开发。首先,需要确定数据交换的方式和格式,在设计接口时需要定义数据的字段和数据类型。其次,需要编写代码来实现数据的传输和转换,以确保数据在两个系统之间的准确性和完整性。最后,需要进行测试和调试,以确保接口的稳定性和可靠性。 在接口开发过程中,需要考虑以下几个方面:首先,需要确定接口的功能和目的,例如实现销售订单的传输、物料库存的同步等。其次,需要连接SAP和WMS的系统和数据库,确保数据的一致性和实时性。最后,需要考虑异常情况的处理,如网络中断、数据格式错误等,确保系统的稳定性和可靠性。 通过SAP和WMS接口开发,可以实现以下优势:首先,实现了不同系统之间的数据共享和同步,提高了工作效率和准确性。其次,降低了人工操作的错误率,提高了业务流程的自动化和标准化程度。最后,提供了更多的数据分析和决策支持,帮助企业做出更好的商业决策和优化流程。 综上所述,SAP和WMS之间的接口开发是为了实现数据的互通和共享,它能够提高企业的工作效率和准确性,优化业务流程,提供更好的数据分析和决策支持。 ### 回答3: SAP (Systems, Applications and Products)是一套全球知名的企业资源规划软件系统,能够实现企业内各个部门的信息共享和数据管理。WMS (Warehouse Management System)是仓库管理系统,用于管理仓库的各个环节,包括入库、出库、库存管理等。 对于SAP和WMS之间的接口开发,主要是将两个系统之间的数据进行交互和同步。由于SAP和WMS的数据结构和功能有所不同,需要通过开发接口来实现数据的传输和转换。 接口开发的关键是确定数据交换的方式和内容。可以使用不同的技术和协议,如Web Service、RESTful API等进行数据的传输。在开发过程中,需要的主要步骤包括:确定数据的来源和目标、定义数据的格式和规范、编写数据转换的逻辑和程序、测试和调试接口的功能和性能等。 在SAP和WMS之间的接口开发中,需要考虑以下几个方面的内容:首先,确定需要交换的数据,包括入库单、出库单、库存变更等信息;其次,确定数据的传输方式,如实时同步、定时批量等;再次,需要考虑数据的转换和映射,将两个系统的数据进行匹配和转化;最后,需要确保接口的高效和稳定性,保证数据的准确和及时性。 总而言之,SAP和WMS之间的接口开发,能够实现两个系统之间的数据同步和共享,提高企业的信息管理和仓库管理效率。通过合理的接口开发,能够更好地实现企业的物流和供应链管理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值