科目余额微服务接口
# 1、接口介绍
在财务项目开发过程或者第三方系统对接时会有需要查询科目余额的或者核算维度余额的场景,为此提供了此余额接口供使用,可以按照科目或者核算维度的角度查询**单组织某个期间**余额数据。余额接口调用通过以下微服务方式调用。
```java
String result = DispatchServiceHelper.invokeBizService("fi", "gl", "BalanceService", "getBalance", param.toString());
```
# 2、使用说明
将微服务需要的参数封装成一个类,在使用时只需要够构造微服务对应的参数类,然后设置后对应的参数,调用就可以返回余额数据。下面会对使用的参数类以及先关的一些关键点进行介绍。
## 2.1、微服务参数类构造
调用余额表接口需要先构造对应的参数类,然后序列化传递给微服务接口使用。接口参数类如下:
```java
public class BalanceQueryParam {
//查询字段
private List<String> selectors = new ArrayList<String>();
//核算组织(必录)
private long orgId;
//科目表(必录)
private long accountTableId;
//账簿类型(必录)
private long bookTypeId;
//期间(必录)
private long periodId;
//币别(不设置则查所有币别)
private long currencyId;
//科目:<核算维度:值>
private Map<Long, List<Map<String, Long>>> accountAssgrp = new HashMap<>();
//分组汇总字段
private List<String> groupBys = new ArrayList<String>();
//是否扣减损益类金额
private boolean isSubstractPL = false;
//指定科目查询
private boolean isSpecialAccount = true;
public void addSelector(String selector) {
selectors.add(selector);
}
public void addGroupBy(String groupBy) {
groupBys.add(groupBy);
}
/**
* 以下省略getter和 setter方法
*/
}
```
## 2.2、参数类字段说明
| 字段 | 说明 | 备注 |
| ------------ | ------------ | ------------ |
| selectors | **余额表金额字段** 字段标识对应gl_balance元数据 | 必录,**只传金额字段** |
| orgId | 核算组织 | 必录 |
| bookTypeId | 账簿类型 | 必录 |
| accountTableId | 查询科目表 | 非必录 |
| periodId | 查询期间 | 必录 |
| currencyId | 币别 | 非必录,不录则查所有币别,综合本位币是所有币别的本位币汇总 |
| accountAssgrp | 科目维度Map参数,下文详细展开 | 科目非必录; 如需查所有科目则不传科目,只能查核算维度组合ID,无法按指定维度汇总查询 |
| groupBys | 汇总字段,**余额表非金额字段** 字段标识对应gl_balance元数据 | 必录,**非金额字段,除了金额字段的其他字段**; 查period期间字段则只查询当期有发生的数据,当期无发生不返回 |
| isSubstractPL | 是否扣减结转损益发生 | 默认为false |
|isSpecialAccount| true:只返回传参科目余额; false:返回传参科目上下级科目 | 默认为true; 注:查所有科目时,改为false |
accountAssgrp 科目数据传递在此详细说明下:
key是科目对应版本的ID,value是一个List<Map<String, Long>>,对应多个维度信息,Map中key是核算维度的flexfield,value是对应的核算维度基础资料值ID。**flexfield对应核算维度bd_asstacttype(表名t_bas_flex_property系统库)的fflexfield的值,是该维度的唯一标识。**
## 2.3、查找对应版本可用科目数据
科目基础资料是存在版本化的情况的,也就是一个编码会对应到多条数据,微服务接口需要传对应版本的科目id,如果不是前端界面已经传了对应版本的科目id过来,而是自己通过编码去查库的话,需要根据期间找到对应版本的科目记录。查询方式如下:
```java
//假设查询科目1001对应的id 期间period:2021年5期
long orgId = 100000L;
long acctTableId = 1L;
Date enddate = period.getDate("enddate");
//当前组织可用的科目
QFilter forgId = BaseDataServiceHelper.getBaseDataFilter("bd_accountview", orgId);
//科目表过滤
QFilter faccttableId = new QFilter("accounttable", QCP.equals, acctTableId);
//科目编码
QFilter facct = new QFilter("number", QCP.equals, "1001");
//科目生效日期过滤
QFilter fdate = new QFilter("startdate", QCP.less_equals, enddate)
.and(new QFilter("enddate", QCP.large_equals, enddate));
QueryServiceHelper.queryDataSet("", "bd_accountview", "id", new QFilter[]{forgId, faccttableId, facct, fdate}, null);
```
## 2.4、余额表gl_balance字段说明
| 字段 | 说明 | 备注 |
| ------------ | ------------ | ------------ |
| org | 核算组织 | |
| booktype | 账簿类型 | |
| period | 期间 | 有凭证发生的期间,如果无凭证发生的期间则不会记录余额 |
| endperiod | 结束期间 | 该维度下一个发生期间,无下一期则该值为99999999999L,表示最大期间 |
| accounttable | 科目表 | |
| account | 科目 | |
| currency | 币别 | |
| assgrp | 核算维度 | 多维度的唯一组合ID,例如:客户A供应商b;如需按指定维度汇总,则不能查该字段;查科目所有维度则需二开解析维度组合ID |
| measureunit | 计量单位 | |
| beginfor | 期初原币金额 | |
| beginlocal | 期初本位币金额 | |
| beginqty | 期初数量 | |
| debitfor | 本期借方原币金额 | |
| debitlocal | 本期借方本位币金额 | |
| creditfor | 本期贷方原币金额 | |
| creditlocal | 本期贷方本位币金额 | |
| debitqty | 本期借方数量 | |
| creditqty | 本期贷方数量 | |
| yeardebitfor | 本年借方原币金额 | |
| yeardebitlocal | 本年借方本位币金额 | |
| yearcreditfor | 本年贷方原币金额 | |
| yearcreditlocal | 本年贷方本位币金额 | |
| yeardebitqty | 本年借方数量 | |
| yearcreditqty | 本年贷方数量 | |
| endfor | 期末原币金额 | |
| endlocal | 期末本位币金额 | |
| endqty | 期末数量 | |
| count | 凭证分录数 | 用于记录对应余额的汇总凭证发生数 |
| comassist1 | 公共维度1 | 对应科目表的公共维度1,不启用公共维度则不需要关心 |
| comassist2 | 公共维度2 | 对应科目表的公共维度2,不启用公共维度则不需要关心 |
**延伸字段说明**:
科目余额方向字段:account.dc dc,方向值:借方dc=1,贷方dc=-1
注:接口所有余额数据都是按余额方向展示, 如endlocal=-100,dc=1, 表示借方期末余额-100;如需正数显示,方向和余额皆需乘以-1,则是贷方期末余额100
**需二开字段说明**:
**本期发生额** = (本期借方-本期贷方)*余额方向;
**本年累计发生额** = (本年借方-本年贷方)*余额方向;
**年初余额** = 期末余额-本年累计发生额;
注意以上字段都需区分本位币(后缀local)和原币字段(后缀for),比如本位币的本期发生额=(debitlocal-creditlocal)*余额方向;
# 3、使用示例
## 示例1
查询2001科目下客户(f0001)维度的人民币发生金额,类似在核算维度余额表查询2001科目,维度选了客户进行查询。
```java
public static void test1(){
BalanceQueryParam param = new BalanceQueryParam();
param.setOrgId(51L);
param.setBookTypeId(237528347981256704L);
param.setCurrencyId(1);
param.setAccountTableId(1L);
param.setPeriodId(120210050L);
//设置查询字段(金额字段)
param.addSelector("creditlocal");
param.addSelector("debitlocal");
param.addSelector("endfor");
//设置汇总字段(非金额字段),按客户f001和科目汇总;f0001 : 核算维度flexfield字段值,表示科目2001按客户维度汇总;
param.addGroupBy("f0001");
param.addGroupBy("account");
List<Map<String, Long>> list = new ArrayList<>();
Map<String,Long> flex = new HashMap<>();
flex.put("f0001", null);
list.add(flex);
//查询期间
DynamicObject period = BusinessDataServiceHelper.loadSingleFromCache(120210050L, "bd_period");
//根据期间和编码查找对应版本的科目id
long acctId = getAcctId(period, "1002");
param.setAccountAssgrp(acctId, list);
String result = DispatchServiceHelper.invokeBizService("fi", "gl", "BalanceService", "getBalance", param.toString());
}
/**
* 查找对应组织当前期间可用版本科目id
*/
private long getAcctId(DynamicObject period, String number){
long orgId = 51L;
long acctTableId = 1L;
Date enddate = period.getDate("enddate");
/**
* 查科目必要前置条件,查对应期间版本的科目ID
*/
//当前组织可用的科目
QFilter forgId = BaseDataServiceHelper.getBaseDataFilter("bd_accountview", orgId);
//科目表过滤
QFilter faccttableId = new QFilter("accounttable", QCP.equals, acctTableId);
//日期过滤
QFilter fdate = new QFilter("startdate", QCP.less_equals, enddate)
.and(new QFilter("enddate", QCP.large_equals, enddate));
/**
* 自定义查科目条件,按所需条件查科目
*/
//科目编码
QFilter facct = new QFilter("number", QCP.equals, number);
DynamicObject acct = QueryServiceHelper.queryOne( "bd_accountview", "id",
new QFilter[]{forgId, faccttableId, facct, fdate});
return acct.getLong("id");
}
```
## 示例2
查询2001科目下的当期发生明细数据(带维度),如果只想查询科目汇总余额,查询字段去掉assgrp,group by 字段加上account即可
```java
BalanceQueryParam param = new BalanceQueryParam();
param.setOrgId(51L);
param.setBookTypeId(237528347981256704L);
param.setCurrencyId(1);
param.setAccountTableId(1L);
param.setPeriodId(120210050);
//设置汇总字段(非金额字段)--查assgrp维度组合ID,则需二开解析维度组合
param.addGroupBy("account");
param.addGroupBy("assgrp");
//设置金额字段
param.addSelector("creditlocal");
param.addSelector("debitlocal");
param.addSelector("endfor");
//科目2001ID--1239224618951136256L
param.setAccountAssgrp(1239224618951136256L, null);
String result = DispatchServiceHelper.invokeBizService("fi", "gl", "BalanceService", "getBalance", param.toString());
```
## 示例3
查询非明细科目的客户维度汇总余额,相当于在核算维度余额表选择非明细科目2201,查询客户维度,查询2201底下的核算维度按客户维度进行汇总。
```java
public static void test3(){
/*
* 2201 客户
* 2201.01 客户
* 2201.02 客户/供应商
* 2201.03 客户
* 查询2201底下的明细科目,按客户进行汇总
*/
BalanceQueryParam param = new BalanceQueryParam();
param.setOrgId(51L);
param.setBookTypeId(237528347981256704L);
param.setCurrencyId(1L);
param.setAccountTableId(1L);
param.setPeriodId(120210050L);
//设置查询字段(金额字段)
param.addSelector("creditlocal");
param.addSelector("debitlocal");
param.addSelector("endfor");
//添加分组字段(非金额字段)
param.addGroupBy("f0001");
param.addGroupBy("account");
List<Map<String, Long>> list = new ArrayList<>();
Map<String,Long> flex = new HashMap<>();
flex.put("f0001", null);
list.add(flex);
//科目2001及其下级科目id
DynamicObject period = BusinessDataServiceHelper.loadSingleFromCache(120210050L, "bd_period");
List<Long> ids = getAcctId(period, "2001");
for(Long acctId : ids){
param.setAccountAssgrp(acctId, list);
}
String result = DispatchServiceHelper.invokeBizService("fi", "gl", "BalanceService", "getBalance", param.toString());
}
private List<Long> getAcctId(DynamicObject period, String number){
long orgId = 100000L;
long acctTableId = 1;
Date enddate = period.getDate("enddate");
//当前组织可用的科目
QFilter forgId = BaseDataServiceHelper.getBaseDataFilter("bd_accountview", orgId);
//科目表过滤
QFilter faccttableId = new QFilter("accounttable", QCP.equals, acctTableId);
/**
* 自定义查科目条件,按所需条件查科目
*/
//科目编码查下级,如2001查2000101和200102
QFilter facct = new QFilter("number", QCP.like, number+"%");
//日期过滤
QFilter fdate = new QFilter("startdate", QCP.less_equals, enddate)
.and(new QFilter("enddate", QCP.large_equals, enddate));
DataSet ds = QueryServiceHelper.queryDataSet("", "bd_accountview", "id",
new QFilter[]{forgId, faccttableId, facct, fdate}, null);
List<Long> ids = new ArrayList<>();
for(Row row : ds){
ids.add(row.getLong("id"));
}
return ids;
}
```
# 4、常见问题
**1. 为什么返回的期初期末数据跟数据库表储存的不一致?**
返回的期初期末余额是当前科目对应余额方向的余额。
**2. 为什么当期无发生的数据,余额表界面能查到,接口无数据返回?**
查询字段和group by字段不要加入期间字段,不然只会查询本期有发生的数据。
**3. 只查客户维度的汇总数据,怎么写?**
查某个核算维度字段时,groupby的字段名要用该核算维度flexfield的值。
**4. 返回的数据不全,怎么查询全量数据?**
微服务接口只返回10W数据,超过该数据量推荐使用SDK的余额表接口查询。kd.sdk.fi.bd.service.balance.BalanceExecutorSdk#getBalance
**5. 多科目多维度组合怎么查?**
可一次批量查,科目+维度组合是独立查询,不会受其他科目和维度的影响。
比如:查科目1001+客户所有,1002+供应商a,b(若值太多请查所有),1003+客户所有+人员所有;
条件设置accountAssgrp{1001:[{客户:null}],1002:[{供应商:a},{供应商:b}],1003:[{客户:null,人员:null}]}
groupby.addGroupBy(客户flexfield值);groupby.addGroupBy(供应商flexfield值);groupby.addGroupBy(人员flexfield值);
返回结果:
|account |客户flexfield值|供应商flexfield值|人员flexfield值|endlocal|
|-|-|-|-|-|
|1001|100000001L|null|null|100|
|1002|null|100000002L|null|100|
|1003|100000001L|null|100000003L|100|
按类似表格形式返回数据,科目没有过滤维度的列用null或者0L值填充;
**6. 两个维度的查询场景,以下方式的区别?**
```java
// 第一种方式
List<Map<String, Long>> list = new ArrayList<>();
Map<String,Long> flex = new HashMap<>();
flex.put("f0001", null);
list.add(flex);
Map<String,Long> flex1 = new HashMap<>();
flex1.put("f0002", null);
list.add(flex1);
//第二种方式
List<Map<String, Long>> list = new ArrayList<>();
Map<String,Long> flex = new HashMap<>();
flex.put("f0001", null);
flex.put("f0002", null);
list.add(flex);
```
第一种方式先查询f0001,再查询f0002的结果;第二种方式就是查询该科目的两个维度,类似在核算维度余额表选一个科目,选择两个核算维度。
科目余额微服务接口
# 1、接口介绍在财务项目开发过程或者第三方系统对接时会有需要查询科目余额的或者核算维度余额的场景,为此提供了此余额接口供使用,可以...
点击下载文档
本文2024-09-22 22:38:43发表“云星瀚知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-xinghan-127942.html
您需要登录后才可以发表评论, 登录登录 或者 注册
最新文档
热门文章