付款申请单

一、背景

客户已经做了预付款。然后走【采购发票】-【应付事项】流程 【应付事项】下推财务【付款】时,增加审批流流程:【付款申请单】。 【付款申请单】审批通过后进入财务【付款】单

通过此案例我们来学习开发技术,业务逻辑并不完善,请注意

二、能力清单

编号 能力清单
1 开放平台接口调用
2 页面设计器常用操作
3 自定义模态框
4 无强关联数据页面显示
5 常用函数使用

三、业务流程

  • 开发单据:【付款申请单】

图1

四、操作流程

图2

五、数据建模

5.1、应付事项实体

  • 该实体仅用来构建页面,不存储业务数据
操作 描述
名称 应付事项
编码 fioap
父实体
引用接口
属性 编码 名称 类型 引用
currency_moneyDigit 原币币种精度 数值
currency_priceDigit 原币价格精度 数值
code 单据编号 文本
billdirection 单据方向 文本
oriTax 原币税额 文本
provisionalestimateflag 是否暂估 文本
exchRate 汇率 文本
accentity_name 会计主体 文本
taxsubject 税目 文本
deatil_supplier_name 表体供应商 文本
vouchdate 单据日期 文本
natCurrency_name 本币币种名称 文本
billtype 应付事项类型 文本
balance 余额 文本
period_code 会计期间 文本
supplier_name 供应商名称 文本
exchangeRateType_digit 汇率精度 文本
auditstatus 审批状态 文本
currency_name 币种名称 文本
oriSum 金额 文本
tradetype_name 交易类型名称 文本
localbalance 本币余额 文本
natSum 本币含税金额 文本
natCurrency_moneyDigit 本币币种金额精度 文本
natCurrency_priceDigit 本币币种单价精度 文本
exchangeRateType_name 汇率类型名称 文本
accountdate 立账日期 文本
oriMoney 原币金额 文本
natMoney 本币金额 文本
basebilltype_name 事项类型名称 文本

5.2、付款申请实体

  • 可通过复制已有实体:付款申请主表快速实现
操作 描述
名称 付款申请
编码 payment
父实体
引用接口 审批 自动编码 交易类型
属性 编码 名称 类型 引用
vouchdate 单据日期 日期
accentity 会计主体 单选引用 会计主体 bd.adminOrg.FinanceOrgVO
oriSum 付款金额 数值
natSum 本币金额 数值
balance 余额 数值
supplier 供应商 单选引用 供应商 aa.vendor.Vendor
supplierbankname 收款银行 文本
supplierbankaccount_accountname 收款银行账户 文本
period 会计期间 单选引用 会计期间 bd.period.Period
settlemode 结算方式 单选引用 结算方式 aa.settlemethod.SettleMethod
currency 币种 单选引用 币种 bd.currencytenant.CurrencyTenantVO
currency_priceDigit 币种单价精度 数值
currency_moneyDigit 币种金额精度 数值
natCurrency 本币币种 单选引用 币种 bd.currencytenant.CurrencyTenantVO
natCurrency_priceDigit 本币币种单价精度 数值
natCurrency_moneyDigit 本币币种金额精度 数值
exchRate 汇率 数值
dept 部门 单选引用 部门 bd.adminOrg.AdminOrgVO
operator 业务员 单选引用 员工 bd.staff.StaffNew
exchangeRateType_digit 汇率类型金额精度 数值
exchangeRateType 汇率类型 单选引用 汇率类型 bd.exchangeRate.ExchangeRateTypeVO
project 项目 单选引用 项目 bd.project.ProjectVO
enterprisebankaccount 付款银行账户id 单选引用 企业银行账户 bd.enterprise.OrgFinBankacctVO
description 备注 文本
noteno 票据号 文本
org 采购组织 单选引用 采购组织 bd.adminOrg.PurchaseOrgVO
cashaccount 付款现金账户 单选引用 企业现金账户 bd.enterprise.OrgFinCashacctVO
isSync 是否同步 单选 是否同步
orderno 订单编号 文本
sourcebillnum 原单金额 数值

5.3、付款申请支付明细实体

操作 描述
名称 付款申请支付明细
编码 paybillbapply
父实体 付款申请
引用接口
属性 编码 名称 类型 引用
expenseitem 费用项目 单选引用 费用项目 bd.expenseitem.ExpenseItem
oriSum 金额 数值
natSum 本币金额 数值
customer_code 客户编码 文本
customer 客户 单选引用 客户档案 aa.merchant.Merchant
supplier 供应商 单选引用 供应商 aa.vendor.Vendor
employee 员工 单选引用 员工 bd.staff.StaffNew
dept 部门 单选引用 部门 bd.adminOrg.AdminOrgVO
project 项目 单选引用 项目 bd.project.ProjectVO
orderno 订单编号 文本
description 备注 文本
product 物料 单选引用 物料 pc.product.Product
quickType_code 款项类型 单选 款项类型

5.4、预付款申请实体

  • 可通过复制【预付款申请】实体快速实现
  • 该实体仅用来构建页面,不存储业务数据
操作 描述
名称 预付款申请ch
编码 prepaymentch
父实体 付款申请
引用接口
属性 编码 名称 类型 引用
vouchdate 单据日期 日期
accentity 会计主体 单选引用 会计主体 bd.adminOrg.FinanceOrgVO
oriSum 付款金额 数值
natSum 本币金额 数值
balance 余额 数值
supplier 供应商 单选引用 供应商 aa.vendor.Vendor
supplierbankname 收款银行 文本
supplierbankaccount_accountname 收款银行账户 文本
period 会计期间 单选引用 会计期间 bd.period.Period
settlemode 结算方式 单选引用 结算方式 aa.settlemethod.SettleMethod
currency 币种 单选引用 币种 bd.currencytenant.CurrencyTenantVO
currency_priceDigit 币种单价精度 数值
currency_moneyDigit 币种金额精度 数值
natCurrency 本币币种 单选引用 币种 bd.currencytenant.CurrencyTenantVO
natCurrency_priceDigit 本币币种单价精度 数值
natCurrency_moneyDigit 本币币种金额精度 数值
exchRate 汇率 数值
dept 部门 单选引用 部门 bd.adminOrg.AdminOrgVO
operator 业务员 单选引用 员工 bd.staff.StaffNew
exchangeRateType_digit 汇率类型金额精度 数值
exchangeRateType 汇率类型 单选引用 汇率类型 bd.exchangeRate.ExchangeRateTypeVO
project 项目 单选引用 项目 bd.project.ProjectVO
enterprisebankaccount 付款银行账户id 单选引用 企业银行账户 bd.enterprise.OrgFinBankacctVO
description 备注 文本
noteno 票据号 文本
org 采购组织 单选引用 采购组织 bd.adminOrg.PurchaseOrgVO
cashaccount 付款现金账户 单选引用 企业现金账户 bd.enterprise.OrgFinCashacctVO
isSync 是否同步 单选 是否同步
orderno 订单编号 文本
sourcebillnum 原单金额 数值

六、页面建模

6.1、【付款申请】一主多子页面

  • 新建【付款申请】一主多子类型

图3

图11

6.2、应付事项单表弹框

  • 创建一个单表应付事项页面

图12

  • 进入页面设计器

图13

  • 调整页面布局
  • 删除系统预制的按钮栏,工具栏
  • 新增底部栏,添加两个按钮,实现如下布局

图14

  • 取消按钮绑定事件,点击配置填写以下函数,保存即可

图15


function (event) {
  var viewModel = this;
  //关闭模态框
  viewModel.communication({type:'modal',payload:{data:false}});
}

图19

  • 新增API函数【应付事项列表查询】,如下图

图20


let AbstractAPIHandler = require('AbstractAPIHandler');
  class MyAPIHandler extends AbstractAPIHandler {
   execute(request){
    //使用公共函数--------------begin
    let func1 = extrequire("GT10894AT82.common.getOpenApiToken");
    let res = func1.execute(request);
    let configfun = extrequire("GT10894AT82.common.config");
    let config = configfun.execute(request);
    //使用公共函数--------------end
    var token = res.access_token;
    var deptId = request;
    var requrl = config.config.sandboxopenapiurl+"/yonbip/fi/oap/list?access_token="+token;
    var header = {'Content-Type':"application/json;charset=UTF-8"};
    var apiData = {
      "pageIndex":1,
      "pageSize":20
    }
    var queryQ = request.queryCondition;
    for(let i in queryQ){
      apiData[queryQ[i].itemName] = queryQ[i].value1;
    }
    var strResponse = postman("POST", requrl,JSON.stringify(header),JSON.stringify(apiData));
    var responseObj = JSON.parse(strResponse);
   return {responseObj};
 }
}
exports({"entryPoint":MyAPIHandler});
  • 绑定页面初始化函数,并配置以下函数
  • 函数主要功能调用应付事项API函数

图17


function (event) {
  var viewModel = this;
  //取消自动查询
  viewModel.getParams().autoLoad = false;
  var gridModel = viewModel.getGridModel();
  //设置取消复现框
  gridModel.setState("showCheckBox",false);
  var queryCondition;
  //查询前事件
  viewModel.on("beforeSearch",function(params){
    queryCondition = params.params.condition.commonVOs;
  })
  //查询后事件
  viewModel.on("afterSearch",function(params){
    //调用应付事项接口
    cb.rest.invokeFunction("GT10894AT82.fioap.fiaoplist", {'queryCondition':queryCondition},
      function(err, res) {
        if(err!=null){
          cb.utils.alert(err,"error");
        }else{
          console.log(res);
          //循环增行
          var resP = res.responseObj.data.recordList;
          for(let i in resP){
            if(resP[i].id!=undefined)
            gridModel.appendRow(resP[i]);
          }
        }
    })    
  })
}
  • 确定按钮绑定事件,点击配置填写以下函数,保存即可
  • 新增获取应付事项详情API函数

let AbstractAPIHandler = require('AbstractAPIHandler');
  class MyAPIHandler extends AbstractAPIHandler {
   execute(request){
    //使用公共函数--------------begin
    let func1 = extrequire("GT12951AT32.config.getApiAccessToken");
    let res = func1.execute(request);
    let configfun = extrequire("GT12951AT32.config.baseConfig");
    let config = configfun.execute(request);
    //使用公共函数--------------end
    var token = res.access_token;
    var id = request;
    var requrl = config.config.baseUrl+"/yonbip/fi/oap/detail?access_token="+token+"&id="+id;
    var header = {'Content-Type':"application/json;charset=UTF-8"};
    var strResponse = postman("GET", requrl,JSON.stringify(header));
    var responseObj = JSON.parse(strResponse);
   return {responseObj};
 }
}
exports({"entryPoint":MyAPIHandler});
  • api函数插入付款申请

图22



let AbstractAPIHandler = require('AbstractAPIHandler');
  class MyAPIHandler extends AbstractAPIHandler {
   execute(request){
      var id = request.id;
      var code = request.code;
      //校验code是否已经存在
      var isCodeExist = ObjectStore.queryByYonQL('select code, id from GT12951AT32.GT12951AT32.paymentnishch where dr=0 and orderno="'+code+'"');
      if(isCodeExist.length>0){
        throw new Error("该单据已经生成付款申请单");
      }
      //获取应付事项详情
      let func1 = extrequire("GT12951AT32.fiaoplist.fioapdetail");
      let fiaopD = func1.execute(id);
      var insertData = fiaopD.responseObj.data;
      insertData.paybillbnishch2List = insertData.oapDetail;
      //查出来付款金额---只考虑子表有一条数据的情况,不做太复杂了
      var orderno = insertData.paybillbnishch2List[0].orderno;
      //设置原单金额
      insertData.sourcebillnum = insertData.oriSum;
      //查询付款申请进行抵消
      var chSum = ObjectStore.queryByYonQL('select oriSum, id,isSync from GT12951AT32.GT12951AT32.prepaymentnishch where dr=0 and  orderno="'+orderno+'"');
      if(chSum.length>0){
        for(let j in chSum){
          if(chSum[j].isSync=="2"){
            throw new Error("当前未同步付款的预付款申请流程");
          }
          insertData.oriSum = insertData.oriSum-chSum[j].oriSum;
        }
      }
      //子表款项类型=应付款
      insertData.paybillbnishch2List[0].quickType_code = "6";
      insertData.paybillbnishch2List[0].oriSum = insertData.oriSum;
      insertData.paybillbnishch2List[0].natSum = insertData.oriSum;
      insertData.paybillbnishch2List[0].product = insertData.paybillbnishch2List[0].material;//子表物料
      //主表金额
      insertData.natSum = insertData.oriSum;
      insertData.balance = insertData.oriSum;
      insertData.sourcebillcode = insertData.code;
      insertData.bustype = "2281177064296712";
      delete insertData.code;
      delete insertData.oapDetail;
      var res = ObjectStore.insert("GT12951AT32.GT12951AT32.paymentnishch2",insertData,"294cbb05");
   return {res};
 }
}
exports({"entryPoint":MyAPIHandler});

图16


function (event) {
  var viewModel = this;
  //获取表格模型
  var gridModel = viewModel.getGridModel();
  //获取表格选中行
  var rows = gridModel.getSelectedRows();
  if(rows.length==0)return cb.utils.alert("请选择数据","alert");
  //执行保存逻辑
  cb.rest.invokeFunction("GT10894AT82.fioap.insertPayMentApply", {id:rows[0].id,code:rows[0].code},
  function(err, res) {
    if(err!=null){
      cb.utils.alert(err.message);
    }else{
      //获取父model
      var parentViewModel = viewModel.getCache('parentViewModel');
      //属性父model页面
      parentViewModel.execute("refresh");
      //关闭模态框
      viewModel.communication({type:'modal',payload:{data:false}});
    }
  })
}

6.3、付款申请列表新增【应付事项】按钮打开【应付事项弹框】

  • 进入列表页面设计器新增一个按钮,修改多语标题为【应付事项】
  • 页面布局可根据情况调整,不影响功能效果

图8

  • 应付事项按钮绑定点击事件,功能:打开【应付事项弹框】

图21


function (event) {
  var viewModel = this;
  let data = {
    billtype: 'VoucherList',// 单据类型
    billno: '9b372483',// 单据号
    params: {
      mode: 'browse', 
    }
  };
  //打开一个单据,并在当前页面显示
  cb.loader.runCommandLine('bill', data, viewModel);
}

6.4、【付款申请列表】功能测试

  • 预览,点击付款申请

图23

  • 点击模态框查询

图23

  • 选择一行数据保存,付款申请新增一条数据

图23 图23

6.5、【付款申请】卡片页面设计器内容调整

  • 进入卡片页面设计器,调整布局

图4

  • 如下图调整布局,可根据情况调整,不影响功能效果

图5

  • 设置原单金额、是否同步不允许修改,其它根据情况调整,不影响功能效果

图6

6.6、【付款申请】卡片联查预付款

  • 实现效果如下

图6 图6

  • 功能实现
  • 调整预付款列表AP函数

图6



let AbstractAPIHandler = require('AbstractAPIHandler');
  class MyAPIHandler extends AbstractAPIHandler {
   execute(request){
     var orderno = request.orderno;
     var sql = "select distinct vouchdate ,accentity ,accentity.name, oriSum, natSum, balance, supplier, supplierbankname, supplierbankaccount_accountname,"+
                   " period,settlemode,currency,currency_priceDigit,currency_moneyDigit,natCurrency,code "+
                   "from GT12951AT32.GT12951AT32.prepaymentnishch where orderno = '"+orderno+"'";
     var res = ObjectStore.queryByYonQL(sql);
   return {res};
 }
}
exports({"entryPoint":MyAPIHandler});
  • 初始化函数绑定前端函数,调用预付款列表API函数

图6


function (event) {
  var viewModel = this;

  //数据加载完成之后
  viewModel.on("afterLoadData",function(){
    getPrePay();    
  })

  function getPrePay(){
    var gridModel = viewModel.get("paybillbapply0526List");
    //获取预付款表格
    var gridModelPre = viewModel.get("prepaymentchList");
    if(gridModelPre.getRows().length>0){
      //说明已经请求过数据不再发起请求
      return true;
    }
    var orderno = viewModel.get('orderno').getValue();
    cb.rest.invokeFunction("GT10894AT82.prepayment.getInfoByOrderNo", {orderno:orderno},
    function(err, res) {
      if(err!=null){
        cb.utils.alert(JSON.stringify(err));
      }else{
        var data = res.res
        for(let i in data){
           if(data[i].id!=undefined)
           preGridModel.appendRow(data[i]);
        }
      }
    })
  }
}

6.7、【付款申请】卡片,付款功能实现

  • 目的:点击付款,调用付款保存接口,生成付款单

  • 经过前面调用开放平台接口发现,可以经基本的请求进行一个封装

  • 新增获取开放平台接口公共方法

图19


let AbstractAPIHandler = require('AbstractAPIHandler');
  class MyAPIHandler extends AbstractAPIHandler {
   execute(request){
    var reqBodyData = request.reqBody;
    var uri = request.uri;
     //获取开放平台token
    let tokenFun = extrequire("GT12951AT32.config.getApiAccessToken");
    let tokenRes = tokenFun.execute(request);
    var access_token = tokenRes.access_token;
    //获取配置文件基础路径
    let configFun = extrequire("GT12951AT32.config.baseConfig");
    let configRes = configFun.execute(request);
    var baseUrl = configRes.config.baseUrl;
    var useUrl = baseUrl+uri+"?access_token="+access_token;
    var header = {'Content-Type':"application/json;charset=UTF-8"};
    var strResponse = postman("POST", useUrl,JSON.stringify(header),JSON.stringify(reqBodyData));
    var responseObj = JSON.parse(strResponse);
   return {responseObj};
 }
}
exports({"entryPoint":MyAPIHandler});
  • 新增付款保存api函数

图6


let AbstractAPIHandler = require('AbstractAPIHandler');
  class MyAPIHandler extends AbstractAPIHandler {
   execute(request){
    var main = request.params.billData;
    main._status = "Insert";
    var ch = request.params.billData.paybillbapply0526List;
    for(let i in ch){
      ch[i]._status = "Insert";
    }
    main.PayBillb = ch;
    delete main.paybillbapply0526List;
    var apiData = {"data":[main]};
    //apiData请求数据
    //使用公共函数--------------begin
    let func1 = extrequire("GT10894AT82.common.getOpenApiToken");
    let res = func1.execute(request);
    let configfun = extrequire("GT10894AT82.common.config");
    let config = configfun.execute(request);
    //使用公共函数--------------end
    var token = res.access_token;
    var deptId = request;
    var requrl = config.config.sandboxopenapiurl+"/yonbip/fi/payment/save?access_token="+token;
    var header = {'Content-Type':"application/json;charset=UTF-8"};
    var strResponse = postman("POST", requrl,JSON.stringify(header),JSON.stringify(apiData));
    var responseObj = JSON.parse(strResponse);
    if(responseObj.data.failCount==0){
      var object = {id:main.id,isSync:"1"};
      ObjectStore.updateById("GT10894AT82.GT10894AT82.paymentapply0526",object,"b1c1b909");
    }
   return {responseObj};
 }
}
exports({"entryPoint":MyAPIHandler});
  • 付款申请卡片增加付款按钮,绑定前端函数点击事件,调用付款保存api函数

图6 图6


let AbstractAPIHandler = require('AbstractAPIHandler');
  class MyAPIHandler extends AbstractAPIHandler {
   execute(request){
    //调用了付款保存接口
    request.uri = "/yonbip/fi/payment/save";
    var reqBody = request.params.billData;
    reqBody._status = "Insert";
    reqBody.tradetype = reqBody.bustype;
    var ch = reqBody.paybillbnishch2List;
    for(let i  in ch){
      ch[i]._status = "Insert";
    }
    reqBody.PayBillb = ch;
    delete reqBody.paybillbnishch2List;
    request.reqBody = {"data":[reqBody]};
    let apiUtilFunc = extrequire("GT12951AT32.config.openApiUtils");
    let apiUtilRes = apiUtilFunc.execute(request);
    if(apiUtilRes.responseObj.data.failCount==0){
      var object = {id:reqBody.id,isSync:"1"};
      var res = ObjectStore.updateById("GT12951AT32.GT12951AT32.paymentnishch2",object,"294cbb05");
    }
   return {responseObj:apiUtilRes.responseObj};
 }
}
exports({"entryPoint":MyAPIHandler});

七、配置审批流

图6 图6

八、付款测试

  • 预付款联查

图6 图6

  • 付款前校验

图6

  • 审批单据

图6

  • 付款,多次付款会禁止

图6 图6

  • 查看付款单,款项类型为:应付款
  • 可根据情况,付款保存函数字段对应情况,此处仅实现流程并未完全对应

图6 图6

Copyright © 用友 -【生态技术部】 2021 all right reserved,powered by Gitbook修订时间: 2021-09-29 17:44:21

results matching ""

    No results matching ""