成本科目和项目数仓同步逻辑按照接口文档优化
This commit is contained in:
parent
bfbb917ed4
commit
6d46dc5b26
|
@ -31,6 +31,7 @@ public class DobeDWaccountTask extends AbstractTask implements Plugin {
|
|||
|
||||
private static Log log = LogFactory.getLog(DobeDWaccountTask.class);
|
||||
private static final String entityName = "recos_stdcostaccount";//标准成本科目实体 供应链库 表名 t_recos_scostaccount
|
||||
private static final String acctViewEntity = "bd_accountview";//会计科目实体 财务库 表名 T_BD_Account
|
||||
// private static final String accEntity = "costaccountentry";//科目分录实体 供应链库 表名 t_recos_costaccount
|
||||
// private static final String projectEntity = "repmd_projectbill";//项目实体 表名 t_repmd_projectbill
|
||||
private static final String dw_menthod = "mdm_costsubject";
|
||||
|
@ -40,7 +41,7 @@ public class DobeDWaccountTask extends AbstractTask implements Plugin {
|
|||
//调用数仓查询接口
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
Request request = new Request.Builder().url(DobeDWUtils.dwUrl+dw_menthod)
|
||||
.post(DobeDWUtils.createRequestBody("",1))
|
||||
.post(DobeDWUtils.createRequestBody("account",1))
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Authorization", DobeDWUtils.appCode)
|
||||
.build();
|
||||
|
@ -56,7 +57,7 @@ public class DobeDWaccountTask extends AbstractTask implements Plugin {
|
|||
}
|
||||
JSONObject json_body = JSON.parseObject(resultData);
|
||||
//接口返回的数据进行了分页
|
||||
int totalNum = json_body.getIntValue("totalNum");//分页-SQL查询总数据量
|
||||
// int totalNum = json_body.getIntValue("totalNum");//分页-SQL查询总数据量
|
||||
//解析接口返回值,与系统数据比较
|
||||
// String projectnumber = json_body.getString("projectnumber");
|
||||
// DynamicObject projectinfo = QueryServiceHelper.queryOne(projectEntity,"id,billno",new QFilter[]{new QFilter("billno","=",projectnumber)});
|
||||
|
@ -66,47 +67,61 @@ public class DobeDWaccountTask extends AbstractTask implements Plugin {
|
|||
// }
|
||||
//根据id查找标准成本科目的表头信息
|
||||
long bzkmid = 2012525353133704192l;//测试id
|
||||
// long bzkmid = 2012525353133704192l;//正式id
|
||||
// long bzkmid = 2037039962179791872l;//正式id
|
||||
DynamicObject billinfo = BusinessDataServiceHelper.loadSingle(entityName,new QFilter[]{new QFilter("id","=",bzkmid)});
|
||||
// if(billinfo == null){
|
||||
// billinfo = BusinessDataServiceHelper.newDynamicObject(entityName);
|
||||
// billinfo.set("project",projectinfo.getLong("id"));
|
||||
// }
|
||||
if(billinfo == null){
|
||||
//根据标准科目id未找到对应记录
|
||||
DobeDWUtils.saveLog(bzkmid+"","数仓成本科目同步","","根据标准科目ID未找到对应记录:"+bzkmid,false,"定时任务");
|
||||
return;
|
||||
}
|
||||
String acctid = null;
|
||||
String number = null;
|
||||
String name = null;
|
||||
// String longnumber = null;
|
||||
// String longname = null;
|
||||
String ciaccountflag = null;
|
||||
// String ciaccountflag = null;
|
||||
// String apportionway = null;
|
||||
// String taxrate = null;
|
||||
String isleaf = null;
|
||||
String level = null;
|
||||
// String isleaf = null;
|
||||
String kjkm_num = null;
|
||||
String kjkm_name = null;
|
||||
String parentid = null;
|
||||
DynamicObject acctinfo = null;
|
||||
Map<String,DynamicObject> parentAccts = new HashMap<>();//现有科目集合
|
||||
// DynamicObject mapAcctinfo = null;
|
||||
DynamicObject acctViewinfo = null;
|
||||
Map<String,DynamicObject> parentAccts = new HashMap<>();//现有成本科目集合
|
||||
// Map<String,DynamicObject> mappingAccts = new HashMap<>();//现有成本科目映射集合
|
||||
Map<String,DynamicObject> acctViewMap = new HashMap<>();//会计科目缓存
|
||||
JSONArray detailsJson = json_body.getJSONArray("data");
|
||||
DynamicObjectCollection doDetails = billinfo.getDynamicObjectCollection("costaccountentry");
|
||||
for (int i = 0; i < doDetails.size(); i++) {
|
||||
acctinfo = doDetails.get(i);
|
||||
//以数仓科目id作为key,科目对象为value
|
||||
parentAccts.put(acctinfo.getString("caentry_srcid"),acctinfo);
|
||||
}
|
||||
// DynamicObjectCollection mapDetails = billinfo.getDynamicObjectCollection("accountmapentry");
|
||||
// for (int i = 0; i < mapDetails.size(); i++) {
|
||||
// mapAcctinfo = mapDetails.get(i);
|
||||
// //以成本科目长编码作为key,映射对象为value
|
||||
// mappingAccts.put(mapAcctinfo.getString("amentry_longnumber"),mapAcctinfo);
|
||||
// }
|
||||
//循环入参,判断哪些科目该修改,哪些该新增
|
||||
for (int i = 0; i < detailsJson.size(); i++) {
|
||||
json_body = detailsJson.getJSONObject(i);
|
||||
acctid = json_body.getString("costsubject_id");//科目id
|
||||
number = json_body.getString("costsubject_code");//科目编号
|
||||
name = json_body.getString("costsubject_name");//科目名称
|
||||
kjkm_num = json_body.getString("accsubject_code");//会计科目编码
|
||||
kjkm_name = json_body.getString("accsubject_name");//会计科目名称
|
||||
// longnumber = json_body.getString("longnumber");//科目长编号
|
||||
// longname = json_body.getString("longname");//科目长名称
|
||||
ciaccountflag = json_body.getString("ciaccountflag");//科目类别 非建安科目and建安科目
|
||||
// ciaccountflag = json_body.getString("ciaccountflag");//科目类别 非建安科目and建安科目
|
||||
// apportionway = json_body.getString("apportionway");//分摊方式
|
||||
// taxrate = json_body.getString("taxrate");//税率
|
||||
isleaf = json_body.getString("isleaf");//是否叶子节点
|
||||
// isleaf = json_body.getString("isleaf");//是否叶子节点
|
||||
// level = json_body.getString("level");//科目级次
|
||||
parentid = json_body.getString("costsubject_pid");//科目父级id
|
||||
if(DobeDWUtils.isEmpty(number) || DobeDWUtils.isEmpty(name) || DobeDWUtils.isEmpty(isleaf)
|
||||
|| DobeDWUtils.isEmpty(acctid)){
|
||||
if(DobeDWUtils.isEmpty(number) || DobeDWUtils.isEmpty(name) || DobeDWUtils.isEmpty(acctid)){
|
||||
//如果组织ID和组织编码 名称是空的,则跳过此记录
|
||||
log.info(String.format("成本科目入参为空异常:%s", json_body.toJSONString()));
|
||||
continue;
|
||||
|
@ -124,18 +139,18 @@ public class DobeDWaccountTask extends AbstractTask implements Plugin {
|
|||
acctinfo.set("caentry_enable", true);//默认 启用
|
||||
acctinfo.set("caentry_isstdaccount", true);//是否标准科目
|
||||
acctinfo.set("caentry_standlibflag", true);//是否标准科目库
|
||||
acctinfo.set("caentry_isleaf", "1");//是否叶子节点,新增默认为true
|
||||
acctinfo.set("caentry_longnumber", number);//科目长编号
|
||||
acctinfo.set("caentry_fullname", name);//科目长名称
|
||||
//将此次新增的科目放到现有科目集合中,方便后续科目能获取到父级科目
|
||||
parentAccts.put(acctid,acctinfo);
|
||||
}
|
||||
//已存在,做更新 编号、名称、长编号、名称、科目类别等
|
||||
acctinfo.set("caentry_number", number);
|
||||
acctinfo.set("caentry_name", name);
|
||||
acctinfo.set("caentry_ciaccountflag", ciaccountflag);//科目类别 建安 1 非建安 0
|
||||
acctinfo.set("caentry_ciaccountflag", "1");//科目类别 建安 1 非建安 0 默认都是建安类
|
||||
// acctinfo.set("caentry_apportionway", null);//分摊方式 基础资料
|
||||
// acctinfo.set("caentry_taxrate", taxrate);//税率
|
||||
acctinfo.set("caentry_longnumber", number);//科目长编号
|
||||
acctinfo.set("caentry_fullname", name);//科目长名称
|
||||
acctinfo.set("caentry_isleaf", isleaf);
|
||||
//创建组织 caentry_createorg
|
||||
//组织 caentry_org
|
||||
//业务组织 caentry_useorg
|
||||
|
@ -147,10 +162,38 @@ public class DobeDWaccountTask extends AbstractTask implements Plugin {
|
|||
acctinfo.set("caentry_fullname", parentAccts.get(parentid).getString("caentry_fullname")+"_"+name);
|
||||
//科目级次=父级科目级次+1
|
||||
acctinfo.set("caentry_level", parentAccts.get(parentid).getInt("caentry_level")+1);
|
||||
//父级科目的是否叶子节点为否
|
||||
parentAccts.get(parentid).set("caentry_isleaf", "0");//是否叶子节点
|
||||
}else{
|
||||
//没有父节点的是根节点,级次是1
|
||||
acctinfo.set("caentry_level", 1);
|
||||
}
|
||||
//处理成本科目与会计科目的映射关系--该关系并不是有个分表来存储,如下代码注释
|
||||
// mapAcctinfo = mappingAccts.get(acctinfo.getString("caentry_longnumber"));
|
||||
// if(mapAcctinfo == null){
|
||||
// //根据科目长编码未找到对应映射关系,则新增一个映射关系
|
||||
// mapAcctinfo = mapDetails.addNew();
|
||||
// mapAcctinfo.set("amentry_longnumber",acctinfo.getString("caentry_longnumber"));//科目长编码
|
||||
// mapAcctinfo.set("amentry_name",name);//科目名称
|
||||
// mapAcctinfo.set("amentry_isleaf",acctinfo.getString("caentry_isleaf"));//是否叶子
|
||||
// mapAcctinfo.set("amentry_ciaccountflag","1");//科目类别 建安 1 非建安 0 默认都是建安类
|
||||
// mapAcctinfo.set("amentry_enable",true);//是否启用 默认启用
|
||||
// mapAcctinfo.set("amentry_level",acctinfo.getInt("caentry_level"));//级次
|
||||
// }
|
||||
//设置对应会计科目字段id
|
||||
if(!DobeDWUtils.isEmpty(kjkm_num)){
|
||||
acctViewinfo = acctViewMap.get(kjkm_num);
|
||||
if(acctViewinfo == null){
|
||||
acctViewinfo = QueryServiceHelper.queryOne(acctViewEntity,"id,number,longnumber",new QFilter[]{new QFilter("longnumber","=",kjkm_num)});
|
||||
}
|
||||
if(acctViewinfo == null){
|
||||
DobeDWUtils.saveLog(acctinfo.getString("caentry_longnumber"),"数仓项目同步",json_body.toString(),"会计科目在金蝶中找不到:"+kjkm_num,false,"定时任务");
|
||||
}else{
|
||||
acctViewMap.put(kjkm_num,acctViewinfo);
|
||||
// mapAcctinfo.set("amentry_account",acctViewinfo.getLong("id"));
|
||||
acctinfo.set("caentry_account",acctViewinfo.getLong("id"));
|
||||
}
|
||||
}
|
||||
}
|
||||
SaveServiceHelper.save(new DynamicObject[]{billinfo});
|
||||
}
|
||||
|
|
|
@ -29,20 +29,21 @@ import java.util.Map;
|
|||
public class DobeDWprojectTask extends AbstractTask implements Plugin {
|
||||
private static final String entityName = "repmd_projectbill";//表名 t_repmd_projectbill
|
||||
private static Log log = LogFactory.getLog(DobeDWprojectTask.class);
|
||||
private static final String dw_menthod = "htt";
|
||||
private static final String dw_menthod = "mdm_projectinfo";
|
||||
|
||||
@Override
|
||||
public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
Request request = new Request.Builder().url(DobeDWUtils.dwUrl+dw_menthod)
|
||||
.post(DobeDWUtils.createRequestBody("",1))
|
||||
.post(DobeDWUtils.createRequestBody("project",1))
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Authorization", DobeDWUtils.appCode)
|
||||
.build();
|
||||
|
||||
String resultData = null;
|
||||
Response response = null;
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
response = client.newCall(request).execute();
|
||||
resultData = response.body().string();
|
||||
log.info("项目接口返回结果:\n{}", resultData);
|
||||
} catch (IOException e) {
|
||||
|
@ -52,46 +53,77 @@ public class DobeDWprojectTask extends AbstractTask implements Plugin {
|
|||
JSONObject json_body = JSON.parseObject(resultData);
|
||||
//接口返回的数据进行了分页
|
||||
int totalNum = json_body.getIntValue("totalNum");//分页-SQL查询总数据量
|
||||
handleProject(json_body);
|
||||
int queryCount = DobeDWUtils.getQueryCount(totalNum);
|
||||
if(queryCount > 1){
|
||||
//查询次数不止一次,需要分页查询
|
||||
for (int i = 2; i <= queryCount; i++) {
|
||||
request = new Request.Builder().url(DobeDWUtils.dwUrl+dw_menthod)
|
||||
.post(DobeDWUtils.createRequestBody("project",i))
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Authorization", DobeDWUtils.appCode)
|
||||
.build();
|
||||
try {
|
||||
response = client.newCall(request).execute();
|
||||
resultData = response.body().string();
|
||||
} catch (IOException e) {
|
||||
log.info(String.format("组织对应关系接口异常:%s", e.getMessage()));
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
json_body = JSON.parseObject(resultData);
|
||||
handleProject(json_body);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void handleProject(JSONObject json_body) {
|
||||
//解析接口返回值,与系统数据比较
|
||||
JSONArray detailsJson = json_body.getJSONArray("data");
|
||||
|
||||
String fbillno = null;//项目编号
|
||||
String fbillname = null;//项目名称
|
||||
String fprojectstageid = null;//项目阶段 repmd_projectstages t_repmd_projectstage
|
||||
String fversionnum = null;//版本号
|
||||
String fisleaf = null;//是否叶子节点
|
||||
// String fversionnum = null;//版本号
|
||||
// String fisleaf = null;//是否叶子节点
|
||||
String faddress = null;//项目地址
|
||||
String forgid = null;//所属组织
|
||||
String ffiorgid = null;//核算组织
|
||||
String fparentid = null;//上级项目id
|
||||
String forgid = null;//所属组织-行政组织
|
||||
Date project_getdate = null;//项目获取时间
|
||||
String fdwid = null;//数仓项目id
|
||||
DynamicObject orginfo = null;
|
||||
DynamicObject projectinfo = null;
|
||||
DynamicObject projectstageinfo = null;
|
||||
for (int i = 0; i < detailsJson.size(); i++) {
|
||||
json_body = detailsJson.getJSONObject(i);
|
||||
fbillno = json_body.getString("fbillno");
|
||||
fbillname = json_body.getString("fbillname");
|
||||
fversionnum = json_body.getString("fversionnum");
|
||||
fisleaf = json_body.getString("fisleaf");
|
||||
forgid = json_body.getString("forgid");
|
||||
fprojectstageid = json_body.getString("fprojectstageid");
|
||||
fparentid = json_body.getString("fparentid");
|
||||
if(DobeDWUtils.isEmpty(fbillno) || DobeDWUtils.isEmpty(fbillname) || DobeDWUtils.isEmpty(forgid)){
|
||||
fbillno = json_body.getString("project_code");
|
||||
fbillname = json_body.getString("project_name");
|
||||
faddress = json_body.getString("addr");
|
||||
// fisleaf = json_body.getString("fisleaf");
|
||||
forgid = json_body.getString("org_code");
|
||||
project_getdate = json_body.getDate("project_getdate");
|
||||
fprojectstageid = json_body.getString("project_stage");
|
||||
fdwid = json_body.getString("project_id");
|
||||
if(DobeDWUtils.isEmpty(fbillno) || DobeDWUtils.isEmpty(fbillname) || DobeDWUtils.isEmpty(forgid) || DobeDWUtils.isEmpty(fdwid)){
|
||||
log.info(String.format("项目接口入参为空异常:%s", json_body.toJSONString()));
|
||||
continue;
|
||||
}
|
||||
//根据项目编号查找是否已存在
|
||||
projectinfo = BusinessDataServiceHelper.loadSingle(entityName,new QFilter[]{new QFilter("billno","=",fbillno)});
|
||||
//根据数仓id查找项目是否已存在
|
||||
projectinfo = BusinessDataServiceHelper.loadSingle(entityName,new QFilter[]{new QFilter("qeug_dwid","=",fdwid)});
|
||||
//项目阶段表名:t_repmd_projectstage
|
||||
projectstageinfo = QueryServiceHelper.queryOne("repmd_projectstages","id,number",new QFilter[]{new QFilter("number","=",fprojectstageid)});
|
||||
if(projectinfo != null){
|
||||
if("C".equals(projectinfo.getString("billstatus"))){
|
||||
//如果项目已审核,则不进行修改
|
||||
continue;
|
||||
}
|
||||
//已存在,做更新 名称 阶段 版本号等信息;组织、编号、是否叶子节点不能更新;需要前台操作
|
||||
projectinfo.set("billname", fbillname);
|
||||
projectinfo.set("fullname", fbillname);//项目全称
|
||||
if(projectstageinfo != null){
|
||||
projectinfo.set("projectstage", projectstageinfo.getLong("id"));//项目阶段
|
||||
}
|
||||
projectinfo.set("versionnum", fversionnum);
|
||||
projectinfo.set("address", faddress);
|
||||
projectinfo.set("acquiredate", project_getdate);
|
||||
projectinfo.set("billstatus", "A");//单据状态 A保存 B已提交 C已审核
|
||||
projectinfo.set("showflag", true);//是否列表显示
|
||||
projectinfo.set("enable", 1);//是否启用
|
||||
|
@ -105,27 +137,30 @@ public class DobeDWprojectTask extends AbstractTask implements Plugin {
|
|||
//不存在,做新增 根据实体名称创建动态对象
|
||||
projectinfo = BusinessDataServiceHelper.newDynamicObject(entityName);
|
||||
projectinfo.set("billno", fbillno);
|
||||
projectinfo.set("qeug_dwid", fdwid);
|
||||
projectinfo.set("longnumber", fbillno);//长编码
|
||||
projectinfo.set("billname", fbillname);
|
||||
projectinfo.set("fullname", fbillname);//项目全称
|
||||
if(!DobeDWUtils.isEmpty(fparentid)){
|
||||
projectinfo.set("parent", null);//上级项目id
|
||||
projectinfo.set("parentname", null);//上级项目名称
|
||||
}
|
||||
// if(!DobeDWUtils.isEmpty(fparentid)){
|
||||
// projectinfo.set("parent", null);//上级项目id
|
||||
// projectinfo.set("parentname", null);//上级项目名称
|
||||
// }
|
||||
projectinfo.set("bizdate", new Date());//业务日期
|
||||
projectinfo.set("showflag", true);//是否列表显示
|
||||
if(projectstageinfo != null){
|
||||
projectinfo.set("projectstage", projectstageinfo.getLong("id"));//项目阶段
|
||||
}
|
||||
projectinfo.set("versionnum", fversionnum);
|
||||
projectinfo.set("address", faddress);
|
||||
projectinfo.set("acquiredate", project_getdate);
|
||||
orginfo = QueryServiceHelper.queryOne("bos_org","id,number,name",new QFilter[]{new QFilter("fyzjorgid","=",forgid)});
|
||||
if(orginfo != null){
|
||||
projectinfo.set("org", orginfo.getLong("id"));//项目所属组织
|
||||
projectinfo.set("purchaseorg", orginfo.getLong("id"));//项目采购组织同所属组织
|
||||
}else{
|
||||
log.info(String.format("数仓传入的项目所属组织在金蝶中找不到:%s", forgid));
|
||||
DobeDWUtils.saveLog(fbillno,"数仓项目同步",json_body.toString(),"数仓传入的项目所属组织在金蝶中找不到:"+forgid,false,"定时任务");
|
||||
}
|
||||
projectinfo.set("isleaf", fisleaf);
|
||||
projectinfo.set("isleaf", true);
|
||||
projectinfo.set("enable", 1);//是否启用
|
||||
projectinfo.set("billstatus", "A");//单据状态 A保存 B已提交 C已审核
|
||||
projectinfo.set("creator", 43007523L);//创建人默认指定为金小蝶
|
||||
|
|
|
@ -6,14 +6,12 @@ import com.alibaba.fastjson.JSONObject;
|
|||
import kd.bos.context.RequestContext;
|
||||
import kd.bos.dataentity.OperateOption;
|
||||
import kd.bos.dataentity.entity.DynamicObject;
|
||||
import kd.bos.dataentity.entity.DynamicObjectCollection;
|
||||
import kd.bos.exception.KDException;
|
||||
import kd.bos.logging.Log;
|
||||
import kd.bos.logging.LogFactory;
|
||||
import kd.bos.orm.query.QFilter;
|
||||
import kd.bos.schedule.executor.AbstractTask;
|
||||
import kd.bos.servicehelper.BusinessDataServiceHelper;
|
||||
import kd.bos.servicehelper.QueryServiceHelper;
|
||||
import kd.bos.servicehelper.operation.OperationServiceHelper;
|
||||
import kd.bos.servicehelper.operation.SaveServiceHelper;
|
||||
import kd.sdk.plugin.Plugin;
|
||||
|
@ -72,10 +70,10 @@ public class YongyouBIPTask extends AbstractTask implements Plugin {
|
|||
//付款申请
|
||||
requestinfo = prinfo.getDynamicObject("payreqbill");
|
||||
}
|
||||
requestinfo = BusinessDataServiceHelper.loadSingle(requestinfo.getPkValue(),requestinfo.getDataEntityType().getName());
|
||||
requestinfo = BusinessDataServiceHelper.loadSingle(requestinfo.getPkValue(),requestinfo.getDataEntityType().getName().replace("_f7",""));
|
||||
//看用友的实付款查询接口是一个个查询,还是集中查询;这个字段直接从F7实体对象中获取不到,需要扩展F7实体
|
||||
yyid = requestinfo.getString("qeug_yyid");
|
||||
//获取到的yynum为空,则不进行实付查询
|
||||
//获取到的yyid为空,则不进行实付查询
|
||||
if(DobeDWUtils.isEmpty(yyid)){
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -105,6 +105,10 @@ public class DobeDWUtils {
|
|||
JSONObject json_body = new JSONObject();
|
||||
JSONObject json_detail = new JSONObject();
|
||||
json_detail.put("pageSize","300");//一页总条数固定为300
|
||||
if("account".equals(params)){
|
||||
//如果是成本科目或者会计科目,不进行多次取数,默认设置3000长度,一次取完
|
||||
json_detail.put("pageSize","3000");
|
||||
}
|
||||
json_detail.put("pageNum",pageNum);
|
||||
json_body.put("paging",json_detail);
|
||||
if("person".equals(params)){
|
||||
|
@ -129,6 +133,19 @@ public class DobeDWUtils {
|
|||
psjson.put("value","");
|
||||
ps.add(psjson);
|
||||
json_body.put("params",ps);
|
||||
}else if("project".equals(params) || "account".equals(params)){
|
||||
JSONArray ps = new JSONArray();
|
||||
JSONObject psjson = new JSONObject();
|
||||
psjson = new JSONObject();
|
||||
psjson.put("name","s_time");
|
||||
psjson.put("value","");
|
||||
ps.add(psjson);
|
||||
|
||||
psjson = new JSONObject();
|
||||
psjson.put("name","e_time");
|
||||
psjson.put("value","");
|
||||
ps.add(psjson);
|
||||
json_body.put("params",ps);
|
||||
}else{
|
||||
json_body.put("params",new JSONArray());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue