搜索
查看: 5064|回复: 77

[学习] 用友开发-接口

    [复制链接]
 楼主| 发表于 2021-6-19 17:19:56 | 显示全部楼层 |阅读模式
扫码关注微信公众号

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册账号

x
U8接口开发有EAI、API、OpenAPI、SQL、CO 五种方式。其中 EAI、API、OPENAPI是官方推荐且对外提供开放的三种方式。主体功能类似,但细节还是有较大区别。每种方式都有其产生的时间、背景、及其相应要解决的问题。产生的先后顺序如下:EAI->API->OpenAPI;
EAI

各类接口中最早产生的是EAI,主要用来解决数据初始化、数据导入。支持导入Excel和Xml格式的数据。开发人员可以通过编程方式调用其关键组件,实现各种异构数据的导入、互联。是实施导航工具的底层架构
API

U8 API是官方三大接口方式中,功能最强大,实用性最高的对接方式。为U8二次开发提供支持,诞生于开发产业链生态形成时期,面向交付伙伴提供U8二次开发支持。有专门的开发指导工具--“U8API资源管理器”的。

1. 支持对表单 增、删、改、查、审核、弃审 操作

2. 支持 保存前、保存后、删除前、删除后、审核前、审核后 等一系统的 事件处理。

3. 生成的单据支持上下游关联

4. 支持扩展自定义项

表头、表体支持两种赋值方式: XML、BO; 其中 xml 支持扩展自定义项 ,BO(businessObject)不支持扩展自定义项.一般不使用这种格式
OpenApi

主要用于数据对外开放,企业互联互通。需要由用友服务器进行请求中转。不推荐使用。

1. 支持数据的增、删、改、审核、弃审 功能

2. 基于HTTP/HTTPS协议,要求服务器连接外网,需要用友服务器做请求与应答中转

3. 不支持事件功能

4. 不支持上下游单据关联



---------------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------------

以上三种方式,为官方推荐并对外开放方式。U8 V12.5之前版本,提供免费使用.之后版本是需要购买授权付费使用.

---------------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------------
CO

用友内部的接口,不对外开放。主要针对单据的数据操作。由用友的各个业务开发组封装提供。数据格式为xml(dom)

1. 支持单据 增、删、改、查、审核、弃审

1. 支持范围 : 基础档案;供应链--销售,采购,库存,委外;财务--应收应付,凭证,存货核算

      库存   USERPCO.voucherco

      销售   voucherco_sa

      委外?voucherco_om

      采购   voucherco_pu

      ROP计划订单  voucherco_pp

      应付CO类 UFAPBO.clsApvouch

      基础档案? U8SrvTrans.IClsCommon

2. 不支持工作流。 项目上注意做需求规避
SQL

发表于 2021-6-20 14:18:01 | 显示全部楼层
本帖最后由 3560819158 于 2021-6-24 22:40 编辑

2021-04-15 更新腾讯课堂,添加了API-Webserices接口开发视频+代码案例
2021-05-05
更新腾讯课堂,添加了凭证接口开发视频+代码案例
2021-06-04
更新腾讯课堂,添加了工作流接口开发视频+代码案例
加Q群293892902了解下载资料
1.第一章:用友U8二次开发
1.1用友U8按钮开发
1.1.1讲解了如何添加自定义按钮,介绍了在销售订单和销售订单列表添加按钮。
1.1.2讲解如何获取单据界面的数据库链接、登录人员信息、以及表头内容、表体内容,以及如何给单据界面的表头、表体赋值,可以通过一般赋值,或者模拟输入方式赋值。
1.1.3介绍了三个案例。
第一个是引采购订单生产销售订单,快速生单。
第二个是循环表体,根据表体物料编码获取最新单价,更新的含税单价。
第三个是在列表批改备注,会循环列表,识别打勾的行,获取行销售订单号,根据行销售订单号更新对应备注。
1.2用友单据控件事件开发
1.2.1讲解了如何添加单据控件事件开发,介绍了在采购订单表头、表体控件校验后事件,以及表体单击后事件。
1.2.2介绍了三个案例
第一个表头选择供应商事件触发,循环表体根据供应商+存货编码从价格表获取维护单价,赋值给表体的采购单价栏目。
第二个表体选择物料编码事件触发,循环表体根据供应商+存货编码从价格表获取维护单价,赋值给表体的采购单价栏目。
第三个单击表体,根据表体物料编码查询最近一次的采购价格信息,弹窗显示。
1.3用友单据事件开发
1.3.1讲解了如何添加单据事件,介绍了在销售订单添加保存前触发的单据事件开发。
1.3.2介绍了一个案例
第一个是单据保存前检查00001客户不予许销售01000001此类产品,如果检查有此类产品,单据不允许保存,并且提醒用户。
1.4用友嵌入式窗口开发
1.4.1讲解了如何在U8添加菜单以及菜单嵌入式窗口。
1.4.2介绍了一个案例
第一个是开发嵌入式页签窗口,自定义窗口功能,本窗口功能是输入订单号和行号修改销售订单表体备注信息。
1.5用友补丁打包
1.5.1 介绍如何把开发好的dll文件打包成msi补丁,并且介绍如何部署msi补丁。
2.第二章:用友UAP单据开发
2.1用友UAP单据开发设计
2.1.1讲解如何新增UAP单据,设计UAP单据的界面,以及发布UAP单据到ERP。案例是临时发货单据,并且发布到ERP。
2.1.2讲解如何进行UAP单据开发,实现个性化功能发。案例是在临时发货单添加了自定义按钮,按钮功能是点击按钮弹输入框,改变表头备注信息。
3.第三章:用友UAP报表开发
3.1
用友UAP报表开发
3.1.1利用SQL储存过程和UAP报表工具开发自定义报表。并且指导如何添加查询条件以及部署报表到ERP。
4.第四章:用友接口功能开发
4.1介绍用友API方式生单
4.1.1U8 API是官方三大接口方式中,功能最强大,实用性最高的对接方式。为U8二次开发提供支持,诞生于开发产业链生态形成时期,面向交付伙伴提供U8二次开发支持。有专门的开发指导工具--“U8API资源管理器”。
4.1.2介绍了采购订单导入案例以及如何快速调整导入模板,快速学会测试API。
4.2介绍用友U8凭证导入
4.2.1使用用友底层接口方式生成U8凭证,接口具有各种校验,保证导入的凭证准确。
4.2.2提供用友集成的凭证导入案例,供研究。
4.3 介绍类似OpenApi的功能
4.3.1通过webserices+api的方式生成ERP单据,输入参数为json,返回参数也是json,实现web方式生单。
4.3.2介绍了对接文档、接口代码、部署方式、以及调试。
5.1介绍如何调用U8工作流接口
5.1.1 创建独立门户,通过调用U8工作流接口,完成提交、重新提交、审核同意、审核不同意、弃审等操作,实现与U8审批交互。

点评

这个内容挺齐全  详情 回复 发表于 2021-7-17 11:19
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-15 13:23:01 | 显示全部楼层
  • BOM查询
  • --增加了数量
  • DECLARE @partid INT;
  • SELECT @partid = 225323;
  • WITH parts (pbom, pid, cbom, cid, lvl, seq, sortseq, fvflag, pqty, cqty, baseqtyn, baseqtyd)
  • AS (SELECT NULL,
  •            p.ParentId,
  •            p.BomId,
  •            p.ParentId,
  •            0,
  •            0,
  •            0,
  •            1,
  •            CAST(1.0 AS DECIMAL(20, 10)),
  •            1,
  •            1,
  •            1
  •     FROM dbo.bom_parent AS p
  •         JOIN dbo.bom_bom AS b
  •             ON b.BomId = p.BomId
  •     WHERE b.VersionEffDate <= GETDATE()
  •           AND b.VersionEndDate > GETDATE()
  •           AND b.BomType = 1
  •     UNION
  •     SELECT p.BomId,
  •            p.ParentId,
  •            cb.BomId,
  •            c.ComponentId,
  •            0 AS lvl,
  •            CAST(ROW_NUMBER() OVER (PARTITION BY c.BomId ORDER BY c.SortSeq) AS INT) AS seq,
  •            c.SortSeq,
  •            c.FVFlag,
  •            CAST(1.0 AS DECIMAL(20, 10)),
  •            c.BaseQtyN / c.BaseQtyD,
  •            c.BaseQtyN,
  •            c.BaseQtyD
  •     FROM dbo.bom_parent AS p
  •         JOIN dbo.bom_bom AS b
  •             ON b.BomId = p.BomId
  •         JOIN dbo.bom_opcomponent AS c
  •             ON c.BomId = p.BomId
  •         LEFT JOIN dbo.bom_parent AS cb
  •             ON c.ComponentId = cb.ParentId
  •         LEFT JOIN dbo.bom_bom AS bc
  •             ON bc.BomId = cb.BomId
  •     --LEFT JOIN dbo.bom_opcomponentopt bo ON c.OptionsId = bo.OptionsId
  •     WHERE b.VersionEffDate <= GETDATE()
  •           AND b.VersionEndDate > GETDATE()
  •           AND
  •           (
  •               (
  •                   bc.VersionEffDate <= GETDATE()
  •                   AND bc.VersionEndDate > GETDATE()
  •                   AND bc.BomType = 1
  •               )
  •               OR bc.BomId IS NULL
  •           )),
  •      bom
  • AS (SELECT parts.pid AS ancestor,
  •            parts.pbom,
  •            parts.pid,
  •            parts.cbom,
  •            parts.cid,
  •            parts.lvl,
  •            parts.seq,
  •            parts.sortseq,
  •            CAST('01' AS NVARCHAR(50)) AS pseq,
  •            parts.fvflag,
  •            CAST(parts.pqty AS DECIMAL(20, 10)) AS pqty,
  •            CASE parts.fvflag
  •                WHEN 0 THEN
  •                    parts.cqty
  •                ELSE
  •                    parts.pqty * parts.cqty
  •            END AS cqty,
  •            parts.baseqtyn,
  •            parts.baseqtyd
  •     FROM parts
  •     WHERE parts.pbom IS NULL
  •           AND parts.pid = @partid
  •     UNION ALL
  •     SELECT p.ancestor,
  •            c.pbom,
  •            c.pid,
  •            c.cbom,
  •            c.cid,
  •            p.lvl + 1,
  •            c.seq,
  •            c.sortseq,
  •            CAST(p.pseq + '.' + RIGHT('00' + CAST(c.seq AS NVARCHAR(50)), 2) AS NVARCHAR(50)),
  •            c.fvflag,
  •            CAST(p.cqty AS DECIMAL(20, 10)),
  •            CASE c.fvflag
  •                WHEN 0 THEN
  •                    c.cqty
  •                ELSE
  •                    p.cqty * c.cqty
  •            END,
  •            c.baseqtyn,
  •            c.baseqtyd
  •     FROM parts AS c
  •         JOIN bom AS p
  •             ON p.cbom = c.pbom)
  • SELECT *
  • FROM bom AS b
  • ORDER BY b.pseq
  • OPTION (HASH JOIN, MAXRECURSION 10);

复制代码

回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-12 14:01:53 | 显示全部楼层
            部门档案 co同步

            this.rhlog.Text += "时间:" + DateTime.Now.ToString() + " 少侠你正在执行【新增部门档案】任务!\r\n";
            U8Login.clsLogin u8Login = new U8Login.clsLogin();
            String sSubId = "AS";
            String sAccID = txtzt.Text.Trim().ToString();//(default)@002
            String sYear = Convert.ToDateTime(dldate.Text.ToString()).Year.ToString();
            String sDate = Convert.ToDateTime(dldate.Text.ToString()).ToString();
            String sServer = txtserver.Text.ToString();//jx
            String sUserID = txtuser.Text.ToString();//demo
            String sPassword = txtpwd.Text.ToString();
            String sSerial = "";
            if (!u8Login.Login(ref sSubId, ref sAccID, ref sYear, ref sUserID, ref sPassword, ref sDate, ref sServer, ref sSerial))
            {
                this.rhlog.Text += "时间:" + DateTime.Now.ToString() + "  登陆失败,原因:" + u8Login.ShareString + "\r\n";

                return;
            }
            else
            {
                this.rhlog.Text += "时间:" + DateTime.Now.ToString() + " 恭喜少侠登录成功! 获得co秘籍【新增部门档案】\r\n";
                //初始化
                DbHelperSQL.connectionString = u8Login.UFDataConnstringForNet;
                U8SrvTrans.IClsCommon CO = new U8SrvTrans.IClsCommon();
                string conn = u8Login.UFDataConnstringForNet;
                CO.InitNew(u8Login);
                string sErrTmp = "";
                string cXml = ReadFile(@"D:\DepBase.xml");
                bool Result = CO.Add(cXml, "Department", ref sErrTmp);
                if (Result)
                {

                    this.rhlog.Text += "时间:" + DateTime.Now.ToString() + " 新增部门成功!\r\n";
                }
                else
                {
                    this.rhlog.Text += "时间:" + DateTime.Now.ToString() + "   新增部门失败,原因:" + sErrTmp.ToString() + "\r\n";
                }
            }
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-2 21:01:43 | 显示全部楼层
        部门档案 co同步

            this.rhlog.Text += "时间:" + DateTime.Now.ToString() + " 少侠你正在执行【新增部门档案】任务!\r\n";
            U8Login.clsLogin u8Login = new U8Login.clsLogin();
            String sSubId = "AS";
            String sAccID = txtzt.Text.Trim().ToString();//(default)@002
            String sYear = Convert.ToDateTime(dldate.Text.ToString()).Year.ToString();
            String sDate = Convert.ToDateTime(dldate.Text.ToString()).ToString();
            String sServer = txtserver.Text.ToString();//jx
            String sUserID = txtuser.Text.ToString();//demo
            String sPassword = txtpwd.Text.ToString();
            String sSerial = "";
            if (!u8Login.Login(ref sSubId, ref sAccID, ref sYear, ref sUserID, ref sPassword, ref sDate, ref sServer, ref sSerial))
            {
                this.rhlog.Text += "时间:" + DateTime.Now.ToString() + "  登陆失败,原因:" + u8Login.ShareString + "\r\n";

                return;
            }
            else
            {
                this.rhlog.Text += "时间:" + DateTime.Now.ToString() + " 恭喜少侠登录成功! 获得co秘籍【新增部门档案】\r\n";
                //初始化
                DbHelperSQL.connectionString = u8Login.UFDataConnstringForNet;
                U8SrvTrans.IClsCommon CO = new U8SrvTrans.IClsCommon();
                string conn = u8Login.UFDataConnstringForNet;
                CO.InitNew(u8Login);
                string sErrTmp = "";
                string cXml = ReadFile(@"D:\DepBase.xml");
                bool Result = CO.Add(cXml, "Department", ref sErrTmp);
                if (Result)
                {

                    this.rhlog.Text += "时间:" + DateTime.Now.ToString() + " 新增部门成功!\r\n";
                }
                else
                {
                    this.rhlog.Text += "时间:" + DateTime.Now.ToString() + "   新增部门失败,原因:" + sErrTmp.ToString() + "\r\n";
                }
            }
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-14 14:52:51 | 显示全部楼层
   部门档案 co同步

            this.rhlog.Text += "时间:" + DateTime.Now.ToString() + " 少侠你正在执行【新增部门档案】任务!\r\n";
            U8Login.clsLogin u8Login = new U8Login.clsLogin();
            String sSubId = "AS";
            String sAccID = txtzt.Text.Trim().ToString();//(default)@002
            String sYear = Convert.ToDateTime(dldate.Text.ToString()).Year.ToString();
            String sDate = Convert.ToDateTime(dldate.Text.ToString()).ToString();
            String sServer = txtserver.Text.ToString();//jx
            String sUserID = txtuser.Text.ToString();//demo
            String sPassword = txtpwd.Text.ToString();
            String sSerial = "";
            if (!u8Login.Login(ref sSubId, ref sAccID, ref sYear, ref sUserID, ref sPassword, ref sDate, ref sServer, ref sSerial))
            {
                this.rhlog.Text += "时间:" + DateTime.Now.ToString() + "  登陆失败,原因:" + u8Login.ShareString + "\r\n";

                return;
            }
            else
            {
                this.rhlog.Text += "时间:" + DateTime.Now.ToString() + " 恭喜少侠登录成功! 获得co秘籍【新增部门档案】\r\n";
                //初始化
                DbHelperSQL.connectionString = u8Login.UFDataConnstringForNet;
                U8SrvTrans.IClsCommon CO = new U8SrvTrans.IClsCommon();
                string conn = u8Login.UFDataConnstringForNet;
                CO.InitNew(u8Login);
                string sErrTmp = "";
                string cXml = ReadFile(@"D:\DepBase.xml");
                bool Result = CO.Add(cXml, "Department", ref sErrTmp);
                if (Result)
                {

                    this.rhlog.Text += "时间:" + DateTime.Now.ToString() + " 新增部门成功!\r\n";
                }
                else
                {
                    this.rhlog.Text += "时间:" + DateTime.Now.ToString() + "   新增部门失败,原因:" + sErrTmp.ToString() + "\r\n";
                }
            }
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-25 19:45:55 | 显示全部楼层
            联查凭证

            Dim WbTableName As String '凭证临时表
            Dim dbc As ADODB.Connection
            Dim UfDb As New UfDbKit.UfDatabase
            Dim subid As String = "IA"
            Dim cno_id As String
            cno_id = "2021IA0000000019260"

         
            dbc = New ADODB.Connection
            ARPZ.zzLogin = m_login
            UfDb.OpenDatabase(m_login.UfDbName)
            m_ZwPub.InitPubs2("IA", m_login.UfSystemDb, UfDb, m_login.cAcc_Id, m_login.cIYear, m_login.cUserName, m_login.CurDate, m_login.SysPassword)
            ARPZ.zzSys = m_ZwPub
            ARPZ.NewFLCode = "IA,FA,#"
            WbTableName = m_ZwPub.WbTableName
            If dbc.State <> 0 Then dbc.Close()
            dbc.Open(m_login.UfDbName)
            Dim rsTemp As ADODB.Recordset
            Dim Str As String
            rsTemp = New ADODB.Recordset
            If rsTemp.State <> 0 Then rsTemp.Close()
            Str = "select top 1 * from GL_accvouch where coutno_id='" & cno_id & "' "
            rsTemp.CursorLocation = 3
            rsTemp.Open(Str, dbc, 3, 4)
            Dim coutsysname As String = ""
            Dim ioutperiod As String = ""
            Dim coutsign As String = ""
            Dim coutno_id As String = ""
            Dim ioutyear As String = ""
            If Not rsTemp.EOF Then
                coutsysname = rsTemp.Fields("coutsysname").Value
                ioutperiod = rsTemp.Fields("ioutperiod").Value
                coutsign = rsTemp.Fields("coutsign").Value
                coutno_id = rsTemp.Fields("coutno_id").Value
                ioutyear = rsTemp.Fields("ioutyear").Value
            End If
            If Not rsTemp.EOF Then
                ARPZ.StartUpPz("IA", "GL0205", 3, , cousysname, ioutperiod, coutsign, coutno_id, ioutyear)
            End If
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-19 17:22:00 | 显示全部楼层
接口开发一般用API
回复 支持 反对

使用道具 举报

发表于 2021-6-19 21:56:20 | 显示全部楼层
用友的二开平台受限太多,效率太差。
回复 支持 反对

使用道具 举报

发表于 2021-6-21 08:28:00 | 显示全部楼层
EAI相当垃圾,单账套用用还行,多账套时,数据在几个账套里到处窜,新版本不知道有没有解决这个问题。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-21 18:40:01 | 显示全部楼层
hkg36 发表于 2021-6-21 08:28
EAI相当垃圾,单账套用用还行,多账套时,数据在几个账套里到处窜,新版本不知道有没有解决这个问题。 ...

目前很多人都在用CO,少用EAI。

回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-22 18:52:53 | 显示全部楼层
dlfsystem 发表于 2021-6-19 21:56
用友的二开平台受限太多,效率太差。

还好啦,会用的人就觉得方便!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-24 08:32:07 | 显示全部楼层
3560819158 发表于 2021-6-20 14:18
2021-04-15 更新腾讯课堂,添加了API-Webserices接口开发视频+代码案例
2021-05-05 更新腾讯课堂,添加了 ...

兄弟,你这个课程在哪发布
回复 支持 反对

使用道具 举报

发表于 2021-6-27 08:37:39 | 显示全部楼层
完全看不懂- -继续学习
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-28 10:35:18 | 显示全部楼层
aZ-cRY 发表于 2021-6-27 08:37
完全看不懂- -继续学习

如果想转型,得学学
回复 支持 反对

使用道具 举报

发表于 2021-6-29 08:55:01 | 显示全部楼层
849830265 发表于 2021-6-25 19:45
联查凭证

            Dim WbTableName As String '凭证临时表

这个联查凭证好像不行,打开不了凭证。

点评

不行 哪里不行 截图给我  详情 回复 发表于 2021-8-29 22:07
可以的 我是参考文档来做的 测试正常  详情 回复 发表于 2021-6-29 15:46
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-29 15:46:10 | 显示全部楼层
3560819158 发表于 2021-6-29 08:55
这个联查凭证好像不行,打开不了凭证。

可以的  我是参考文档来做的 测试正常

回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-1 08:31:50 | 显示全部楼层
项目:如何在自制插件里清退U8站点

跟踪了系统管理清退站点的语句, 按照它的顺序,更新UA_LOG表里的数据,删除了UA_TASK的任务记录,UA_task里记录删除时还有个触发器,删除时同事删除另外两个表里的记录,最后在插入一条记录到ua_aaLog_base。

不知道有无遗漏,在查询语句里执行后客户端无法清退。
提问者:朱雷   人气:120   提问时间:2013-08-19 08:21
最佳答案

在删除任务之前需要先清除加密,清除加密需要通过程序来完成,代码如下
strSql = "SELECT ISNULL(cTaskID,'') AS cTaskID,ISNULL(uuid,'') AS uuid,ISNULL(cLSSubId,'') AS cLSSubId,ISNULL(cStationSerial,'') AS cStationSerial FROM UA_Tasklog WHERE uuid=N'" & 待清退机器的UUID & "'"
rs.open strSql, g_oconsystem
While Not rs.EOF
Call sysLogin.KickOutWorkStation(rs.Fields("cTaskID").value, rs.Fields("cLSSubId").value, rs.Fields("uuid").value, rs.Fields("cStationSerial").value)
        rs.MoveNext
Wend

其中sysLogin是登陆服务UFSoft.U8.Framework.Login.UI.clsLogin的实例,需要先登陆过才能使用
回复 支持 反对

使用道具 举报

发表于 2021-7-2 15:40:49 | 显示全部楼层
学习,膜拜大佬
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

欢迎关注微信公众号

QQ|Archiver|手机版|小黑屋|用友之家 ( 蜀ICP备07505338号 )川公网安备 51072502110008号

GMT+8, 2021-10-29 04:43 , Processed in 0.073247 second(s), 13 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2005-2020.

快速回复 返回顶部 返回列表