台账插件开发

This commit is contained in:
zhangzhiguo 2024-11-29 12:18:30 +08:00
parent 8407adff59
commit f784dc7c18
7 changed files with 1056 additions and 0 deletions

View File

@ -0,0 +1,101 @@
package zcgj.zcdev.zcdev.fs.plugin.report;
import kd.bos.dataentity.resource.ResManager;
import kd.bos.entity.datamodel.events.PackageDataEvent;
import kd.bos.entity.report.FilterInfo;
import kd.bos.entity.report.ReportQueryParam;
import kd.bos.form.MessageTypes;
import kd.bos.report.events.CellStyleRule;
import kd.bos.report.plugin.AbstractReportFormPlugin;
import kd.sdk.plugin.Plugin;
import java.util.List;
/**
* 领导预算汇总与实际台账
* 报表格式化插件
*/
public class BudgetActuRptListPlugin extends AbstractReportFormPlugin implements Plugin {
private static final String DEV_KEY="zcgj";
private static final String MERGECOLUM= DEV_KEY+"_username";//合并单元格字段
//预算与汇总报表上的所有字段
private static final String[] FIELDS={DEV_KEY+"_user",DEV_KEY+"_username",DEV_KEY+"_year",
DEV_KEY+"_travel",DEV_KEY+"_health",
DEV_KEY+"_abroad_travel",DEV_KEY+"_correspondence",DEV_KEY+"_training",DEV_KEY+"_entertain",
DEV_KEY+"_amounttotal"};
@Override
public void setMergeColums(List<String> columns) {
columns.add(MERGECOLUM);
super.setMergeColums(columns);
}
@Override
public void packageData(PackageDataEvent packageDataEvent) {
super.packageData(packageDataEvent);
}
@Override
public boolean verifyQuery(ReportQueryParam queryParam) {
FilterInfo filter = queryParam.getFilter();
StringBuilder sb = new StringBuilder();
if (filter.getValue("zcgj_query_org") == null){
this.getView().showTipNotification("请选择查询组织!");
return false;
}
return true;
}
@Override
public void setCellStyleRules(List<CellStyleRule> cellStyleRules) {
for (String field : FIELDS) {
CellStyleRule cellStyleRule = new CellStyleRule();
cellStyleRule.setFieldKey(field);// 字段标识
cellStyleRule.setForeColor("#666666");// 前景色
cellStyleRule.setBackgroundColor("#ffc000");// 背景色
cellStyleRule.setDegree(100);// 透明度
cellStyleRule.setCondition(DEV_KEY+"_username = '合计'");// 前置条件值与表达式计算器一致
cellStyleRules.add(cellStyleRule);
}
/* cellStyleRule = new CellStyleRule();
cellStyleRule.setFieldKey(DEV_KEY+"_year");// 字段标识
cellStyleRule.setForeColor("#666666");// 前景色
cellStyleRule.setBackgroundColor("#ffc000");// 背景色
cellStyleRule.setDegree(100);// 透明度
//cellStyleRule1.setCondition("_year = '2021年预算'");// 前置条件值与表达式计算器一致
cellStyleRule.setCondition(DEV_KEY+"_username = '合计'");// 前置条件值与表达式计算器一致
cellStyleRules.add(cellStyleRule);
cellStyleRule = new CellStyleRule();
cellStyleRule.setFieldKey(DEV_KEY+"_travel");// 字段标识
cellStyleRule.setForeColor("#666666");// 前景色
cellStyleRule.setBackgroundColor("#ffc000");// 背景色
cellStyleRule.setDegree(100);// 透明度
//cellStyleRule1.setCondition("_year = '2021年预算'");// 前置条件值与表达式计算器一致
cellStyleRule.setCondition(DEV_KEY+"_username = '合计'");// 前置条件值与表达式计算器一致
cellStyleRules.add(cellStyleRule);
cellStyleRule = new CellStyleRule();
cellStyleRule.setFieldKey(DEV_KEY+"_health");// 字段标识
cellStyleRule.setForeColor("#666666");// 前景色
cellStyleRule.setBackgroundColor("#ffc000");// 背景色
cellStyleRule.setDegree(100);// 透明度
//cellStyleRule1.setCondition("_year = '2021年预算'");// 前置条件值与表达式计算器一致
cellStyleRule.setCondition(DEV_KEY+"_username = '合计'");// 前置条件值与表达式计算器一致
cellStyleRules.add(cellStyleRule);
cellStyleRule = new CellStyleRule();
cellStyleRule.setFieldKey(DEV_KEY+"_amounttotal");// 字段标识
cellStyleRule.setForeColor("#666666");// 前景色
cellStyleRule.setBackgroundColor("#ffc000");// 背景色
cellStyleRule.setDegree(100);// 透明度
//cellStyleRule1.setCondition("_year = '2021年预算'");// 前置条件值与表达式计算器一致
cellStyleRule.setCondition(DEV_KEY+"_username = '合计'");// 前置条件值与表达式计算器一致
cellStyleRules.add(cellStyleRule);*/
super.setCellStyleRules(cellStyleRules);
}
}

View File

@ -0,0 +1,418 @@
package zcgj.zcdev.zcdev.fs.plugin.report;
import kd.bos.algo.*;
import kd.bos.algo.input.CollectionInput;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.report.AbstractReportListDataPlugin;
import kd.bos.entity.report.FilterItemInfo;
import kd.bos.entity.report.ReportQueryParam;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
* 领导预算汇总与实际台账
* 报表取数插件
*/
public class BudgetActuRptQueryPlugin extends AbstractReportListDataPlugin {
private static final Log logger = LogFactory.getLog(BudgetActuRptQueryPlugin.class);
// 格式化日期的格式
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private static final String DEV_KEY="zcgj";
@Override
public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
List<FilterItemInfo> filters = reportQueryParam.getFilter().getFilterItems();
List<Long> applierId = new ArrayList<>();
Long orgId = null;
Date queryDate = null;
for (FilterItemInfo filterItem : filters) {
switch (filterItem.getPropName()) {
case DEV_KEY+"_query_users":
DynamicObjectCollection users = (DynamicObjectCollection)filterItem.getValue();
if(users != null){
for (DynamicObject user : users) {
applierId.add(Long.valueOf(String.valueOf(user.getPkValue())));
}
}
break;
case DEV_KEY+"_query_year":
queryDate = filterItem.getDate();
break;
case DEV_KEY+"_query_org":
orgId = (filterItem.getValue() == null) ? null :Long.valueOf(String.valueOf(((DynamicObject) filterItem.getValue()).getPkValue()));
break;
default:
break;
}
}
//人员预算填报单标识
String Bill_ANNUAL_BUDGET =DEV_KEY+"_annual_budget";
//人员预算单部分字段编码
String[] FIELD_KEY_OF_ANNUAL_BUDGET = {DEV_KEY+"_user", DEV_KEY+"_year",
DEV_KEY+"_travel",DEV_KEY+"_health",
DEV_KEY+"_abroad_travel",DEV_KEY+"_correspondence",DEV_KEY+"_training",DEV_KEY+"_entertain"};
//预算与汇总报表上的所有字段
String[] FIELDS={DEV_KEY+"_user",DEV_KEY+"_username",DEV_KEY+"_year",
DEV_KEY+"_travel",DEV_KEY+"_health",
DEV_KEY+"_abroad_travel",DEV_KEY+"_correspondence",DEV_KEY+"_training",DEV_KEY+"_entertain",
DEV_KEY+"_amounttotal"};
//报表上对应的字段数据类型必须和FIELDS中的字段一一对应
DataType[] DATATYPES ={DataType.LongType,DataType.StringType,DataType.StringType,
DataType.BigDecimalType,DataType.BigDecimalType,
DataType.BigDecimalType,DataType.BigDecimalType,DataType.BigDecimalType,DataType.BigDecimalType,
DataType.BigDecimalType};
//查询预算单数据
StringBuilder selectSettlementFields = new StringBuilder();
selectSettlementFields.append(FIELD_KEY_OF_ANNUAL_BUDGET[0]).append(" AS ").append(FIELDS[0])
.append(", ").append(FIELD_KEY_OF_ANNUAL_BUDGET[1]).append(" AS ").append(FIELDS[2])
.append(", ").append(FIELD_KEY_OF_ANNUAL_BUDGET[2]).append(" AS ").append(FIELDS[3])
.append(", ").append(FIELD_KEY_OF_ANNUAL_BUDGET[3]).append(" AS ").append(FIELDS[4])
.append(", ").append(FIELD_KEY_OF_ANNUAL_BUDGET[4]).append(" AS ").append(FIELDS[5])
.append(", ").append(FIELD_KEY_OF_ANNUAL_BUDGET[5]).append(" AS ").append(FIELDS[6])
.append(", ").append(FIELD_KEY_OF_ANNUAL_BUDGET[6]).append(" AS ").append(FIELDS[7])
.append(", ").append(FIELD_KEY_OF_ANNUAL_BUDGET[7]).append(" AS ").append(FIELDS[8])
;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");
// 创建一个空的DataSet,用于组装报表数据
Collection<Object[]> coll = new ArrayList<Object[]>();
RowMeta rowMeta = RowMetaFactory.createRowMeta(FIELDS, DATATYPES);
CollectionInput inputs = new CollectionInput(rowMeta, coll);
DataSet resultDataSet = Algo.create(this.getClass().getName()).createDataSet(inputs);
if(orgId==null){
return resultDataSet;
}
//获取公司下的所有人
List<Long> orgIds = new ArrayList<>();
orgIds.add(orgId);
List<Long> allUsersOfOrg = UserServiceHelper.getAllUsersOfOrg(orgIds);
if(!applierId.isEmpty()){
allUsersOfOrg = applierId;
}
// 获取当前年份
int currentYear = LocalDate.now().getYear();
//年份显示量
int yearCount = 2;
// 获取前两年的年份
int startYear = currentYear - yearCount;
List<Integer> yearList = new ArrayList<>();
// 输出所有年份
for (int year = startYear; year <= currentYear; year++) {
System.out.println(year);
yearList.add(year);
}
//年份-(预算&实际)/项目/金额
Map<String,Map<String,BigDecimal>> countMap = new HashMap<>();
for (Long userId : allUsersOfOrg) {
Map<String, Object> userInfoByID = UserServiceHelper.getUserInfoByID(userId);
//预算金额 start
String username = String.valueOf(userInfoByID.get("name"));
///项目/金额
Map<String,Map<String,BigDecimal>> userYearMapData= new HashMap<>();
List<QFilter> searchFilterList = new ArrayList<>();
//searchFilterList.add(new QFilter(DEV_KEY+"_year", QCP.equals, getFirstDayOfYear(year)));
searchFilterList.add(new QFilter(DEV_KEY+"_user", QCP.equals,userId ));
DataSet settlementDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName() + Bill_ANNUAL_BUDGET,
Bill_ANNUAL_BUDGET, selectSettlementFields.toString(), searchFilterList.toArray(new QFilter [] {}), null).orderBy(new String[]{DEV_KEY+"_user",DEV_KEY+"_year"});
logger.info(">>> 人员预算单: " + settlementDataSet.toString());
for (Row row : settlementDataSet) {
String formatYear = dateFormat.format(row.getDate(DEV_KEY+"_year"));
BigDecimal travel = row.getBigDecimal(DEV_KEY+"_travel");
BigDecimal health = row.getBigDecimal(DEV_KEY+"_health");
BigDecimal abroadTravel = row.getBigDecimal(DEV_KEY+"_abroad_travel");
BigDecimal training = row.getBigDecimal(DEV_KEY+"_training");
BigDecimal entertain = row.getBigDecimal(DEV_KEY+"_entertain");
BigDecimal correspondence = row.getBigDecimal(DEV_KEY+"_correspondence");
if(userYearMapData.containsKey(formatYear)){
Map<String, BigDecimal> stringBigDecimalMap = userYearMapData.get(formatYear);
BigDecimal travelTotal = stringBigDecimalMap.get("travelTotal");
BigDecimal healthTotal = stringBigDecimalMap.get("healthTotal");
BigDecimal abroadTravelTotal = stringBigDecimalMap.get("abroadTravelTotal");
BigDecimal correspondenceTotal = stringBigDecimalMap.get("correspondenceTotal");
BigDecimal trainingTotal = stringBigDecimalMap.get("trainingTotal");
BigDecimal entertainTotal = stringBigDecimalMap.get("entertainTotal");
BigDecimal totalAmountTotal = stringBigDecimalMap.get("totalAmountTotal");
travelTotal = travelTotal.add(travel);
healthTotal = healthTotal.add(health);
abroadTravelTotal = abroadTravelTotal.add(abroadTravel);
trainingTotal = trainingTotal.add(training);
entertainTotal = entertainTotal.add(entertain);
correspondenceTotal = correspondenceTotal.add(correspondence);
Map<String, BigDecimal> d1 = new HashMap<>();
d1.put("travelTotal",travelTotal);
d1.put("healthTotal",healthTotal);
d1.put("abroadTravelTotal",abroadTravelTotal);
d1.put("trainingTotal",trainingTotal);
d1.put("entertainTotal",entertainTotal);
d1.put("correspondenceTotal",correspondenceTotal);
totalAmountTotal=totalAmountTotal.add(travelTotal).add(healthTotal).add(abroadTravelTotal).add(correspondenceTotal).add(trainingTotal).add(entertainTotal);
d1.put("totalAmountTotal",totalAmountTotal);
userYearMapData.put(formatYear,d1);
}else{
Map<String, BigDecimal> d1 = new HashMap<>();
d1.put("travelTotal",travel);
d1.put("healthTotal",health);
d1.put("abroadTravelTotal",abroadTravel);
d1.put("trainingTotal",training);
d1.put("entertainTotal",entertain);
d1.put("correspondenceTotal",correspondence);
BigDecimal total=travel.add(health).add(abroadTravel).add(training).add(entertain).add(correspondence);
d1.put("totalAmountTotal",total);
userYearMapData.put(formatYear,d1);
}
}
for (Integer year : yearList) {
Object [] tempData = new Object [FIELDS.length];
tempData[0] = userId;
tempData[1] = username;
tempData[2] = year+"年预算";
Map<String, BigDecimal> stringBigDecimalMap = userYearMapData.get(year + "");
if(stringBigDecimalMap!=null){
tempData[3] = stringBigDecimalMap.get("travelTotal");
tempData[4] = stringBigDecimalMap.get("healthTotal");
tempData[5] = stringBigDecimalMap.get("abroadTravelTotal");
tempData[6] = stringBigDecimalMap.get("correspondenceTotal");
tempData[7] = stringBigDecimalMap.get("trainingTotal");
tempData[8] = stringBigDecimalMap.get("entertainTotal");
tempData[9] = stringBigDecimalMap.get("totalAmountTotal");
////年份/(预算&实际)/项目/金额
if(countMap.containsKey(year+"a")){//预算汇总和实际的区分为年份+a,例如2024a
Map<String, BigDecimal> m = countMap.get(year + "a");
BigDecimal travelTotal = m.get("travelTotal");
BigDecimal healthTotal = m.get("healthTotal");
BigDecimal abroadTravelTotal = m.get("abroadTravelTotal");
BigDecimal correspondenceTotal = m.get("correspondenceTotal");
BigDecimal trainingTotal = m.get("trainingTotal");
BigDecimal entertainTotal = m.get("entertainTotal");
BigDecimal totalAmountTotal = m.get("totalAmountTotal");
travelTotal = travelTotal.add( stringBigDecimalMap.get("travelTotal"));
healthTotal = healthTotal.add(stringBigDecimalMap.get("healthTotal"));
abroadTravelTotal = abroadTravelTotal.add(stringBigDecimalMap.get("abroadTravelTotal"));
correspondenceTotal = correspondenceTotal.add(stringBigDecimalMap.get("correspondenceTotal"));
trainingTotal = trainingTotal.add(stringBigDecimalMap.get("trainingTotal"));
entertainTotal= entertainTotal.add(stringBigDecimalMap.get("entertainTotal"));
totalAmountTotal= totalAmountTotal.add(stringBigDecimalMap.get("totalAmountTotal"));
m.put("travelTotal",travelTotal);
m.put("healthTotal",healthTotal);
m.put("abroadTravelTotal",abroadTravelTotal);
m.put("trainingTotal",trainingTotal);
m.put("entertainTotal",entertainTotal);
m.put("correspondenceTotal",correspondenceTotal);
m.put("totalAmountTotal",totalAmountTotal);
countMap.put(year+"a",m);
}else{
Map<String, BigDecimal> m = new HashMap<>();
m.put("travelTotal",stringBigDecimalMap.get("travelTotal"));
m.put("healthTotal",stringBigDecimalMap.get("healthTotal"));
m.put("abroadTravelTotal",stringBigDecimalMap.get("abroadTravelTotal"));
m.put("correspondenceTotal",stringBigDecimalMap.get("correspondenceTotal"));
m.put("trainingTotal",stringBigDecimalMap.get("trainingTotal"));
m.put("entertainTotal",stringBigDecimalMap.get("entertainTotal"));
m.put("totalAmountTotal",stringBigDecimalMap.get("totalAmountTotal"));
countMap.put(year+"a",m);
}
}
coll.add(tempData);
//实际-统计非临时出国的费用报销单数据
DataSet bdMaterialDataSet = getDailyreimbursebillDataSet(userId, year,false);
BigDecimal travelRealTotal = BigDecimal.ZERO;//国内差旅费
BigDecimal abroadTravelTotal = BigDecimal.ZERO;//因公临时出国费
BigDecimal healthRealTotal = BigDecimal.ZERO;//防疫费
BigDecimal correspondenceTotal = BigDecimal.ZERO;//通信费用
BigDecimal trainingTotal = BigDecimal.ZERO;//培训费用
BigDecimal entertainTotal = BigDecimal.ZERO;//业务招待费
BigDecimal totalAmountTotal = BigDecimal.ZERO;//金额合计
for (Row itemRow : bdMaterialDataSet) {
//TODO 继续补充其他费用类型
//汇总国内差旅费 FYXM0015.001防疫费 FYXM002-CUS.001
String itemnumber = itemRow.getString("itemnumber");
String happendateStr = dateFormat.format(itemRow.getDate("happendate"));
BigDecimal expenseamount = itemRow.getBigDecimal("expenseamount");
if(itemnumber.startsWith("FYXM002-CUS.001")){//防疫费
healthRealTotal = healthRealTotal.add(expenseamount);
}else if(itemnumber.startsWith("FYXM002-CUS.002")){//日常费用-通信费用
correspondenceTotal = correspondenceTotal.add(expenseamount);
}else if(itemnumber.startsWith("FYXM002-CUS.003")){//日常费用-培训费用
trainingTotal = trainingTotal.add(expenseamount);
}else if(itemnumber.startsWith("FYXM002-CUS.004")){//日常费用-业务招待费
entertainTotal = entertainTotal.add(expenseamount);
}
}
//统计国内差旅费 er_tripreimbursebill
//报销金额费用项目差旅报销单-差旅费没有勾选了因公临时出国的差旅报销单报销金额
//travelRealTotal = travelRealTotal.add(expenseamount);
//统计因公临时出国费
//报销金额费用报销单报销金额勾选了因公临时出国 er_dailyreimbursebill
//报销金额差旅报销单报销金额勾选了因公临时出国 er_tripreimbursebill
//实际-统计因公临时出国费用报销单数据
DataSet bdMaterialForeignDataSet = getDailyreimbursebillDataSet(userId, year,true);
Object [] tempRealData = new Object [FIELDS.length];
tempRealData[0] = userId;
tempRealData[1] = username;
tempRealData[2] = year+"年实际发生";
tempRealData[3]=travelRealTotal;
tempRealData[4]=healthRealTotal;
BigDecimal totalRealAmount = travelRealTotal.add(healthRealTotal);
tempRealData[9] = totalRealAmount;
coll.add(tempRealData);
if(countMap.containsKey(year+"b") ){//预算汇总和实际的区分为年份+a,例如2024a
Map<String, BigDecimal> m = countMap.get(year + "b");
BigDecimal travelTotalMap = m.get("travelTotal");
BigDecimal healthTotalMap = m.get("healthTotal");
BigDecimal abroadTravelTotalMap = m.get("abroadTravelTotal");
BigDecimal correspondenceTotalMap = m.get("correspondenceTotal");
BigDecimal trainingTotalMap = m.get("trainingTotal");
BigDecimal entertainTotalMap = m.get("entertainTotal");
BigDecimal totalAmountTotalMap = m.get("totalAmountTotal");
travelRealTotal = travelTotalMap.add(travelRealTotal);
healthRealTotal = healthTotalMap.add(healthRealTotal);
abroadTravelTotal = abroadTravelTotalMap.add(abroadTravelTotal);
correspondenceTotal = correspondenceTotalMap.add(correspondenceTotal);
trainingTotal = trainingTotalMap.add(trainingTotal);
entertainTotal= entertainTotalMap.add(entertainTotal);
totalAmountTotal= totalAmountTotalMap.add(totalRealAmount);
m.put("travelTotal",travelRealTotal);
m.put("healthTotal",healthRealTotal);
m.put("abroadTravelTotal",abroadTravelTotal);
m.put("trainingTotal",trainingTotal);
m.put("entertainTotal",entertainTotal);
m.put("correspondenceTotal",correspondenceTotal);
m.put("totalAmountTotal",totalAmountTotal);
countMap.put(year+"b",m);
}else{
Map<String, BigDecimal> m = new HashMap<>();
m.put("travelTotal",travelRealTotal);
m.put("healthTotal",healthRealTotal);
m.put("abroadTravelTotal",abroadTravelTotal);
m.put("trainingTotal",trainingTotal);
m.put("entertainTotal",entertainTotal);
m.put("correspondenceTotal",correspondenceTotal);
m.put("totalAmountTotal",totalAmountTotal);
countMap.put(year+"b",m);
}
}
}
//汇总合计
for (int year = startYear; year <= currentYear; year++) {
Map<String, BigDecimal> stringBigDecimalMap = countMap.get(year + "a");
Object [] totalTempData = new Object [FIELDS.length];
totalTempData[0] = null;
totalTempData[1] = "合计";
totalTempData[2] = year+"年预算";
if(stringBigDecimalMap!=null){
totalTempData[3] = stringBigDecimalMap.get("travelTotal");
totalTempData[4] = stringBigDecimalMap.get("healthTotal");
totalTempData[5] = stringBigDecimalMap.get("abroadTravelTotal");
totalTempData[6] = stringBigDecimalMap.get("correspondenceTotal");
totalTempData[7] = stringBigDecimalMap.get("trainingTotal");
totalTempData[8] = stringBigDecimalMap.get("entertainTotal");
totalTempData[9] = stringBigDecimalMap.get("totalAmountTotal");
}
coll.add(totalTempData);
Map<String, BigDecimal> stringBigDecimalMapReal = countMap.get(year + "b");
Object [] totalRealTempData = new Object [FIELDS.length];
totalRealTempData[0] = null;
totalRealTempData[1] = "合计";
totalRealTempData[2] = year+"年实际发生";
if(stringBigDecimalMapReal!=null){
totalRealTempData[3] = stringBigDecimalMapReal.get("travelTotal");
totalRealTempData[4] = stringBigDecimalMapReal.get("healthTotal");
totalRealTempData[5] = stringBigDecimalMapReal.get("abroadTravelTotal");
totalRealTempData[6] = stringBigDecimalMapReal.get("correspondenceTotal");
totalRealTempData[7] = stringBigDecimalMapReal.get("trainingTotal");
totalRealTempData[8] = stringBigDecimalMapReal.get("entertainTotal");
totalRealTempData[9] = stringBigDecimalMapReal.get("totalAmountTotal");
}
coll.add(totalRealTempData);
}
return resultDataSet;
}
/**
* 获取差旅报销单数据
* @param userId 用户id
* @param year 统计年份
* @param isBusinessForeign 是否因公临时出国
* @return 数据集
*/
private DataSet getDailyreimbursebillDataSet(Long userId, Integer year,Boolean isBusinessForeign) {
LocalDate firstDay = getFirstDayOfYear(year);
LocalDate lastDay = getLastDayOfYear(year);
List<QFilter> searchFilterList = new ArrayList<>();
//searchFilterList.add(new QFilter(DEV_KEY+"_year", QCP.equals, getFirstDayOfYear(year)));
searchFilterList.add(new QFilter("applier", QCP.equals, userId));
searchFilterList.add(new QFilter("expenseentryentity.happendate", QCP.large_equals, firstDay));
searchFilterList.add(new QFilter("expenseentryentity.happendate", QCP.less_equals, lastDay));
searchFilterList.add(new QFilter(DEV_KEY+"_is_business_foreign", QCP.equals, isBusinessForeign));
DataSet bdMaterialDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(),
"er_dailyreimbursebill",
"id,description," +
"expenseentryentity.happendate as happendate," + //费用发生日期
"expenseentryentity.expenseitem.number as itemnumber," + //费用项目编码
"expenseentryentity.expenseamount as expenseamount",searchFilterList.toArray(new QFilter [] {}), null);
return bdMaterialDataSet;
}
// 获取某年份的第一天
public static LocalDate getFirstDayOfYear(int year) {
return LocalDate.of(year, 1, 1);
}
// 获取某年份的最后一天
public static LocalDate getLastDayOfYear(int year) {
return LocalDate.of(year, 12, 31);
}
}

View File

@ -0,0 +1,51 @@
package zcgj.zcdev.zcdev.fs.plugin.report;
import kd.bos.entity.datamodel.events.PackageDataEvent;
import kd.bos.report.events.CellStyleRule;
import kd.bos.report.plugin.AbstractReportFormPlugin;
import kd.sdk.plugin.Plugin;
import java.util.List;
/**
* 差旅费报销抵扣税额统计台账
* 报表格式化插件
*/
public class FeeDeductionRptListPlugin extends AbstractReportFormPlugin implements Plugin {
private static final String MERGECOLUM= "zcgj_username";//合并单元格字段
private static final String DEV_KEY="zcgj";
// 报表字段及数据类型
private static final String[] FIELDS = {
DEV_KEY+"_user", DEV_KEY+"_username", DEV_KEY+"_car_fee", DEV_KEY+"_air_trains_fee",
DEV_KEY+"_car_amount", DEV_KEY+"_car_tax", DEV_KEY+"_air_trains_amount",
DEV_KEY+"_air_trains_tax", DEV_KEY+"_total_amount", DEV_KEY+"_total_fee", DEV_KEY+"_month"
};
@Override
public void setMergeColums(List<String> columns) {
columns.add(MERGECOLUM);
super.setMergeColums(columns);
}
@Override
public void packageData(PackageDataEvent packageDataEvent) {
super.packageData(packageDataEvent);
}
@Override
public void setCellStyleRules(List<CellStyleRule> cellStyleRules) {
for (String field : FIELDS) {
CellStyleRule cellStyleRule = new CellStyleRule();
cellStyleRule.setFieldKey(field);// 字段标识
cellStyleRule.setForeColor("#666666");// 前景色
cellStyleRule.setBackgroundColor("#ffc000");// 背景色
cellStyleRule.setDegree(100);// 透明度
cellStyleRule.setCondition(DEV_KEY+"_username = '合计'");// 前置条件值与表达式计算器一致
cellStyleRules.add(cellStyleRule);
}
super.setCellStyleRules(cellStyleRules);
}
}

View File

@ -0,0 +1,195 @@
package zcgj.zcdev.zcdev.fs.plugin.report;
import kd.bos.algo.*;
import kd.bos.algo.input.CollectionInput;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.report.AbstractReportListDataPlugin;
import kd.bos.entity.report.FilterItemInfo;
import kd.bos.entity.report.ReportQueryParam;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 差旅费报销抵扣税额统计台账
* 报表取数插件
*/
public class FeeDeductionRptQueryPlugin extends AbstractReportListDataPlugin {
private static final Log logger = LogFactory.getLog(FeeDeductionRptQueryPlugin.class);
private static final String DEV_KEY="zcgj";
@Override
public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
List<FilterItemInfo> filters = reportQueryParam.getFilter().getFilterItems();
List<Long> applierId = new ArrayList<>();
for (FilterItemInfo filterItem : filters) {
switch (filterItem.getPropName()) {
case DEV_KEY+"_query_users":
DynamicObjectCollection users = (DynamicObjectCollection)filterItem.getValue();
if(users != null){
for (DynamicObject user : users) {
applierId.add(Long.valueOf(String.valueOf(user.getPkValue())));
}
}
break;
default:
break;
}
}
// 报表字段及数据类型
String[] FIELDS = {
DEV_KEY+"_user", DEV_KEY+"_username", DEV_KEY+"_car_fee", DEV_KEY+"_air_trains_fee",
DEV_KEY+"_car_amount", DEV_KEY+"_car_tax", DEV_KEY+"_air_trains_amount",
DEV_KEY+"_air_trains_tax", DEV_KEY+"_total_amount", DEV_KEY+"_total_fee", DEV_KEY+"_month"
};
DataType[] DATATYPES = {
DataType.LongType, DataType.StringType, DataType.BigDecimalType,
DataType.BigDecimalType, DataType.BigDecimalType, DataType.BigDecimalType,
DataType.BigDecimalType, DataType.BigDecimalType, DataType.BigDecimalType,
DataType.BigDecimalType, DataType.StringType
};
// 初始化 DataSet
RowMeta rowMeta = RowMetaFactory.createRowMeta(FIELDS, DATATYPES);
Collection<Object[]> coll = new ArrayList<>();
CollectionInput inputs = new CollectionInput(rowMeta, coll);
DataSet resultDataSet = Algo.create(this.getClass().getName()).createDataSet(inputs);
// 日期格式化
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM");
// 查询条件
QFilter[] filterArray = new QFilter[1];
if(!applierId.isEmpty()){
//查询申请人下的单据
filterArray[0] = new QFilter("applier", QCP.in, applierId);
}
DataSet bdMaterialDataSet = QueryServiceHelper.queryDataSet(
this.getClass().getName(),
"er_tripreimbursebill",
"id,applier,tripentry.to as to,tripentry.startdate as startdate," +
"tripentry.enddate as enddate,tripentry.entryentity.expenseitem.number as expenseitemnumber," +
"tripentry.entryentity.expenseitem.name as expenseitemname,tripentry.entryentity.expenseitem.attribute as attribute," +
"tripentry.entryentity.orientryamount as orientryamount,tripentry.entryentity.notaxamount as notaxamount," +
"tripentry.entryentity.taxamount as taxamount",
filterArray, null
).orderBy(new String[]{"applier", "startdate"});
// 汇总数据
Map<Long, Map<String, Map<String, BigDecimal>>> allData = new HashMap<>();
for (Row itemRow : bdMaterialDataSet) {
Long applier = itemRow.getLong("applier");
String attribute = itemRow.getString("attribute");
Date startdate = itemRow.getDate("startdate");
String startdateStr = dateFormat.format(startdate);
BigDecimal orientryamount = itemRow.getBigDecimal("orientryamount");
BigDecimal notaxamount = itemRow.getBigDecimal("notaxamount");
BigDecimal taxamount = itemRow.getBigDecimal("taxamount");
allData.computeIfAbsent(applier, k -> new HashMap<>())
.computeIfAbsent(startdateStr, k -> new HashMap<>());
Map<String, BigDecimal> dataMap = allData.get(applier).get(startdateStr);
updateExpenseData(dataMap, attribute, orientryamount, notaxamount, taxamount);
}
// 底层合计
BigDecimal totalCarFee = BigDecimal.ZERO;
BigDecimal totalAirTrainsFee = BigDecimal.ZERO;
BigDecimal totalCarAmount = BigDecimal.ZERO;
BigDecimal totalCarTax = BigDecimal.ZERO;
BigDecimal totalAirTrainsAmount = BigDecimal.ZERO;
BigDecimal totalAirTrainsTax = BigDecimal.ZERO;
// 填充结果
List<Long> sortedAppliers = new ArrayList<>(allData.keySet());
Collections.sort(sortedAppliers);
for (Long applier : sortedAppliers) {
Map<String, Map<String, BigDecimal>> userData = allData.get(applier);
Map<String, Object> userInfo = UserServiceHelper.getUserInfoByID(applier);
String userName = String.valueOf(userInfo.get("name"));
List<String> sortedDates = new ArrayList<>(userData.keySet());
Collections.sort(sortedDates);
for (String month : sortedDates) {
Map<String, BigDecimal> expenseData = userData.get(month);
Object[] rowData = assembleRowData(FIELDS, applier, userName, month, expenseData);
// 累加合计值
totalCarFee = totalCarFee.add((BigDecimal) rowData[2]);
totalAirTrainsFee = totalAirTrainsFee.add((BigDecimal) rowData[3]);
totalCarAmount = totalCarAmount.add((BigDecimal) rowData[4]);
totalCarTax = totalCarTax.add((BigDecimal) rowData[5]);
totalAirTrainsAmount = totalAirTrainsAmount.add((BigDecimal) rowData[6]);
totalAirTrainsTax = totalAirTrainsTax.add((BigDecimal) rowData[7]);
coll.add(rowData);
}
}
// 添加合计行
Object[] totalRow = new Object[FIELDS.length];
totalRow[0] = null; // 用户ID为空
totalRow[1] = "合计"; // 用户名显示为"合计"
totalRow[2] = totalCarFee;
totalRow[3] = totalAirTrainsFee;
totalRow[4] = totalCarAmount;
totalRow[5] = totalCarTax;
totalRow[6] = totalAirTrainsAmount;
totalRow[7] = totalAirTrainsTax;
totalRow[8] = totalCarAmount.add(totalAirTrainsAmount); // 合计金额不含税
totalRow[9] = totalCarFee.add(totalAirTrainsFee); // 合计金额含税
totalRow[10] = null; // 月份为空
coll.add(totalRow);
return resultDataSet;
}
/**
* 更新费用数据
*/
private void updateExpenseData(Map<String, BigDecimal> dataMap, String attribute,
BigDecimal orientryamount, BigDecimal notaxamount, BigDecimal taxamount) {
String[] keys;
if ("2".equals(attribute) || "4".equals(attribute)) {
keys = new String[]{"air_trains_fee", "air_trains_amount", "air_trains_tax"};
} else if ("3".equals(attribute)) {
keys = new String[]{"car_fee", "car_amount", "car_tax"};
} else {
return;
}
dataMap.merge(keys[0], orientryamount, BigDecimal::add);
dataMap.merge(keys[1], notaxamount, BigDecimal::add);
dataMap.merge(keys[2], taxamount, BigDecimal::add);
}
/**
* 组装一行数据
*/
private Object[] assembleRowData(String[] fields, Long userId, String userName,
String month, Map<String, BigDecimal> expenseData) {
Object[] rowData = new Object[fields.length];
rowData[0] = userId;
rowData[1] = userName;
rowData[2] = expenseData.getOrDefault("car_fee", BigDecimal.ZERO);
rowData[3] = expenseData.getOrDefault("air_trains_fee", BigDecimal.ZERO);
rowData[4] = expenseData.getOrDefault("car_amount", BigDecimal.ZERO);
rowData[5] = expenseData.getOrDefault("car_tax", BigDecimal.ZERO);
rowData[6] = expenseData.getOrDefault("air_trains_amount", BigDecimal.ZERO);
rowData[7] = expenseData.getOrDefault("air_trains_tax", BigDecimal.ZERO);
rowData[8] = ((BigDecimal) rowData[4]).add((BigDecimal) rowData[6]); // 合计不含税金额
rowData[9] = ((BigDecimal) rowData[2]).add((BigDecimal) rowData[3]); // 合计报销金额
rowData[10] = month;
return rowData;
}
}

View File

@ -0,0 +1,53 @@
package zcgj.zcdev.zcdev.fs.plugin.report;
import kd.bos.entity.datamodel.events.PackageDataEvent;
import kd.bos.report.events.CellStyleRule;
import kd.bos.report.plugin.AbstractReportFormPlugin;
import kd.sdk.plugin.Plugin;
import java.util.List;
/**
* 领导预算汇总与实际台账
* 报表格式化插件
*/
public class PositionFeesRptListPlugin extends AbstractReportFormPlugin implements Plugin {
private static final String MERGECOLUM= "shxr_username";//合并单元格字段
private static final String CONDITION_FIELD="shxr_username";//条件字段
private static final String DEV_KEY="zcgj";
private static final String[] FIELDS = {
DEV_KEY+"_user", DEV_KEY+"_username", DEV_KEY+"_date",
DEV_KEY+"_billno",DEV_KEY+"_serve_business", DEV_KEY+"_serve_outside",
DEV_KEY+"_serve_significant",DEV_KEY+"_serve_other_business",DEV_KEY+"_serve_souvenir",
DEV_KEY+"_serve_total",DEV_KEY+"_travel",DEV_KEY+"_abroad_travel",
DEV_KEY+"_health",DEV_KEY+"_correspondence",DEV_KEY+"_training",
DEV_KEY+"_total"
};
@Override
public void setMergeColums(List<String> columns) {
columns.add(MERGECOLUM);
super.setMergeColums(columns);
}
@Override
public void packageData(PackageDataEvent packageDataEvent) {
super.packageData(packageDataEvent);
}
@Override
public void setCellStyleRules(List<CellStyleRule> cellStyleRules) {
for (String field : FIELDS) {
CellStyleRule cellStyleRule = new CellStyleRule();
cellStyleRule.setFieldKey(field);// 字段标识
cellStyleRule.setForeColor("#666666");// 前景色
cellStyleRule.setBackgroundColor("#ffc000");// 背景色
cellStyleRule.setDegree(100);// 透明度
cellStyleRule.setCondition("shxr_username = '合计'");// 前置条件值与表达式计算器一致
cellStyleRules.add(cellStyleRule);
}
super.setCellStyleRules(cellStyleRules);
}
}

View File

@ -0,0 +1,114 @@
package zcgj.zcdev.zcdev.fs.plugin.report;
import kd.bos.algo.*;
import kd.bos.algo.input.CollectionInput;
import kd.bos.entity.report.AbstractReportListDataPlugin;
import kd.bos.entity.report.FilterItemInfo;
import kd.bos.entity.report.ReportQueryParam;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 职工探亲休假台账
* 报表取数插件
*/
public class PositionFeesRptQueryPlugin extends AbstractReportListDataPlugin {
private static final Log logger = LogFactory.getLog(PositionFeesRptQueryPlugin.class);
private static final String DEV_KEY="zcgj";
@Override
public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
List<FilterItemInfo> filters = reportQueryParam.getFilter().getFilterItems();
List<Long> applierId = new ArrayList<>();
/* for (FilterItemInfo filterItem : filters) {
switch (filterItem.getPropName()) {
case "_queryuser.id":
Object value = filterItem.getValue();
if(value instanceof ArrayList){
applierId = (ArrayList)value;
}else{
applierId.add(Long.valueOf(value.toString()));
}
break;
default:
break;
}
}*/
// 报表字段及数据类型
String[] FIELDS = {
DEV_KEY+"_user", DEV_KEY+"_username", DEV_KEY+"_date",
DEV_KEY+"_billno",DEV_KEY+"_serve_business", DEV_KEY+"_serve_outside",
DEV_KEY+"_serve_significant",DEV_KEY+"_serve_other_business",DEV_KEY+"_serve_souvenir",
DEV_KEY+"_serve_total",DEV_KEY+"_travel",DEV_KEY+"_abroad_travel",
DEV_KEY+"_health",DEV_KEY+"_correspondence",DEV_KEY+"_training",
DEV_KEY+"_total"
};
DataType[] DATATYPES = {
DataType.LongType,DataType.StringType, DataType.StringType,
DataType.StringType,DataType.BigDecimalType, DataType.BigDecimalType,
DataType.BigDecimalType,DataType.BigDecimalType,DataType.BigDecimalType,
DataType.BigDecimalType,DataType.BigDecimalType,DataType.BigDecimalType,
DataType.BigDecimalType,DataType.BigDecimalType,DataType.BigDecimalType,
DataType.BigDecimalType
};
// 初始化 DataSet
RowMeta rowMeta = RowMetaFactory.createRowMeta(FIELDS, DATATYPES);
Collection<Object[]> coll = new ArrayList<>();
CollectionInput inputs = new CollectionInput(rowMeta, coll);
DataSet resultDataSet = Algo.create(this.getClass().getName()).createDataSet(inputs);
// 日期格式化
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
// 查询条件
QFilter[] filterArray = new QFilter[1];
if(!applierId.isEmpty()){
//查询申请人下的单据
filterArray[0] = new QFilter("applier", QCP.in, applierId);
}
DataSet bdMaterialDataSet = QueryServiceHelper.queryDataSet(
this.getClass().getName(),
"er_tripreimbursebill",
"id,applier,applier.name as appliername,applier.phone as appliernamephone,description," +
"org.name as orgname,triptype.name as triptypename," +
"tripentry.to.name as toname,tripentry.startdate as startdate" ,
filterArray, null
).orderBy(new String[]{"applier", "startdate"});
// 汇总数据
Map<Long, Map<String, Map<String, BigDecimal>>> allData = new HashMap<>();
for (Row itemRow : bdMaterialDataSet) {
Long applier = itemRow.getLong("applier");
String appliername = itemRow.getString("appliername");
String orgname = itemRow.getString("orgname");
String appliernamephone = itemRow.getString("appliernamephone");
Date startdate = itemRow.getDate("startdate");
String startdateStr = dateFormat.format(startdate);
String triptypename = itemRow.getString("triptypename");
String toname = itemRow.getString("toname");
String description = itemRow.getString("description");
Object[] totalRow = new Object[FIELDS.length];
totalRow[0] = applier;
totalRow[1] = appliername;
totalRow[2] = orgname;
totalRow[3] = startdateStr;
totalRow[4] = triptypename;
totalRow[5] = toname;
totalRow[6] = appliernamephone;
totalRow[7] = description;
coll.add(totalRow);
}
return resultDataSet;
}
}

View File

@ -0,0 +1,124 @@
package zcgj.zcdev.zcdev.fs.plugin.report;
import kd.bos.algo.*;
import kd.bos.algo.input.CollectionInput;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.report.AbstractReportListDataPlugin;
import kd.bos.entity.report.FilterItemInfo;
import kd.bos.entity.report.ReportQueryParam;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 职工探亲休假台账
* 报表取数插件
*/
public class VisitRptQueryPlugin extends AbstractReportListDataPlugin {
private static final Log logger = LogFactory.getLog(VisitRptQueryPlugin.class);
private static final String DEV_KEY="zcgj";
@Override
public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
List<FilterItemInfo> filters = reportQueryParam.getFilter().getFilterItems();
List<Long> applierId = new ArrayList<>();
for (FilterItemInfo filterItem : filters) {
switch (filterItem.getPropName()) {
case DEV_KEY+"_query_users":
DynamicObjectCollection users = (DynamicObjectCollection)filterItem.getValue();
if(users != null){
for (DynamicObject user : users) {
applierId.add(Long.valueOf(String.valueOf(user.getPkValue())));
}
}
break;
default:
break;
}
}
// 报表字段及数据类型
String[] FIELDS = {
DEV_KEY+"_user", DEV_KEY+"_username", DEV_KEY+"_department",DEV_KEY+"_holiday_date_start",
DEV_KEY+"_holiday_date_end",
DEV_KEY+"_holiday_type", DEV_KEY+"_holiday_addr", DEV_KEY+"_phone",
DEV_KEY+"_reason"
};
DataType[] DATATYPES = {
DataType.LongType,DataType.StringType, DataType.StringType, DataType.StringType,
DataType.StringType,
DataType.StringType, DataType.StringType, DataType.StringType,
DataType.StringType
};
// 初始化 DataSet
RowMeta rowMeta = RowMetaFactory.createRowMeta(FIELDS, DATATYPES);
Collection<Object[]> coll = new ArrayList<>();
CollectionInput inputs = new CollectionInput(rowMeta, coll);
DataSet resultDataSet = Algo.create(this.getClass().getName()).createDataSet(inputs);
// 日期格式化
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
// 查询条件
List<QFilter> filterList = new ArrayList<>();
filterList.add(new QFilter(DEV_KEY+"_is_visit", QCP.equals, true));
//QFilter[] filterArray = new QFilter[1];
if(!applierId.isEmpty()){
//查询申请人下的单据
//filterArray[0] = new QFilter("applier", QCP.in, applierId);
filterList.add(new QFilter("applier", QCP.in, applierId));
}
QFilter[] array = filterList.toArray(new QFilter[0]);
DataSet bdMaterialDataSet = QueryServiceHelper.queryDataSet(
this.getClass().getName(),
"er_dailyreimbursebill",
"id,applier,applier.name as appliername,applier.phone as appliernamephone,description," +
"org.name as orgname,'探亲休假' as triptypename," +
"zcgj_holiday_address as address," +
"zcgj_holiday_start_time as startdate,zcgj_holiday_end_time as enddate" ,
array, null
).orderBy(new String[]{"applier", "startdate"});
// 汇总数据
Map<Long, Map<String, Map<String, BigDecimal>>> allData = new HashMap<>();
for (Row itemRow : bdMaterialDataSet) {
Long applier = itemRow.getLong("applier");
String appliername = itemRow.getString("appliername");
String orgname = itemRow.getString("orgname");
String appliernamephone = itemRow.getString("appliernamephone");
Date startdate = itemRow.getDate("startdate");
String startdateStr = dateFormat.format(startdate);
Date enddate = itemRow.getDate("enddate");
String enddateStr = dateFormat.format(enddate);
String triptypename = itemRow.getString("triptypename");
String description = itemRow.getString("description");
String address = itemRow.getString("address");
Object[] totalRow = new Object[FIELDS.length];
totalRow[0] = applier;
totalRow[1] = appliername;
totalRow[2] = orgname;
totalRow[3] = startdateStr;
totalRow[4] = enddateStr;
totalRow[5] = triptypename;
totalRow[6] = address;
totalRow[7] = appliernamephone;
totalRow[8] = description;
coll.add(totalRow);
}
return resultDataSet;
}
}