Merge branch 'main' of https://dd3skj.picp.vip/JyuHsin/zhgh_jshvc
This commit is contained in:
@@ -14,6 +14,7 @@ import com.wisedu.casp.sdk.api.mc.recallMsg.RecallMsgResponse;
|
||||
import com.wisedu.casp.sdk.core.Client;
|
||||
import com.wisedu.casp.sdk.core.DefaultClient;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.lang.Lang;
|
||||
@@ -31,6 +32,9 @@ import java.util.List;
|
||||
@IocBean
|
||||
public class SmsJshvcServiceImpl implements SmsService {
|
||||
|
||||
@Inject
|
||||
private TodoPlatformConfig todoPlatformConfig;
|
||||
|
||||
@Override
|
||||
public void sendSingleMessage(String loginName, String content) {
|
||||
this.sendSingleMessage(loginName, "智慧工会", content);
|
||||
@@ -109,7 +113,7 @@ public class SmsJshvcServiceImpl implements SmsService {
|
||||
@Override
|
||||
public void recallMsg(String msgId) {
|
||||
try {
|
||||
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
|
||||
Client client = createClient();
|
||||
RecallMsgRequest request = new RecallMsgRequest();
|
||||
request.setMsgId(msgId);
|
||||
|
||||
@@ -143,7 +147,7 @@ public class SmsJshvcServiceImpl implements SmsService {
|
||||
}
|
||||
try {
|
||||
// 创建客户端
|
||||
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
|
||||
Client client = createClient();
|
||||
SendMsgRequest request = new SendMsgRequest();
|
||||
request.setSubject(title);
|
||||
request.setContent(content);
|
||||
@@ -179,4 +183,15 @@ public class SmsJshvcServiceImpl implements SmsService {
|
||||
log.error("发送企业微信通知失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建待办平台消息客户端,平台地址、appId、appSecret 均从 application 配置读取。
|
||||
*/
|
||||
private Client createClient() {
|
||||
return new DefaultClient(
|
||||
todoPlatformConfig.getTodoPlatformBaseUrl(),
|
||||
todoPlatformConfig.getTodoAppId(),
|
||||
todoPlatformConfig.getTodoAppSecret()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,6 @@ public class SysLoginController {
|
||||
@Inject
|
||||
protected PropertiesProxy conf;
|
||||
|
||||
/*
|
||||
@At("")
|
||||
@Ok("re")
|
||||
@ApiOperation("用户本地登录页面")
|
||||
@@ -71,7 +70,6 @@ public class SysLoginController {
|
||||
public String login(HttpServletRequest req, HttpSession session) {
|
||||
return "beetl:/platform/sys/login.html";
|
||||
}
|
||||
*/
|
||||
|
||||
@At
|
||||
@Ok("re")
|
||||
|
||||
@@ -1,30 +1,48 @@
|
||||
package com.budwk.app.todo.platform;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.nutz.ioc.impl.PropertiesProxy;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
/**
|
||||
* @ClassName TodoPlatformConfig
|
||||
* @Author JyuHsin
|
||||
* @Date 2026/2/25 16:26
|
||||
* @Version 1.0
|
||||
* @Description TODO
|
||||
* @Description 待办平台配置,从 application 配置文件读取平台地址、鉴权参数和接口路径。
|
||||
*/
|
||||
@IocBean(create = "init")
|
||||
@Getter
|
||||
public class TodoPlatformConfig {
|
||||
|
||||
// token 获取
|
||||
public static final String TOKEN_URL = "/accessToken";
|
||||
// 待办平台基础地址
|
||||
public static final String TODO_PLATFORM_BASE_URL = "https://gateway.jshvc.edu.cn";
|
||||
// 待办平台新增或者修改
|
||||
public static final String TODO_PLATFORM_SAVE_OR_UPDATE_URL = "/saveOrUpdate";
|
||||
// 待办平台修改地址
|
||||
public static final String TODO_PLATFORM_MODIFY_URL = "/modifyInfo";
|
||||
// 待办平台删除任务地址
|
||||
public static final String TODO_PLATFORM_DELETE_TASK_URL = "/delete";
|
||||
// 待办平台删除实例地址
|
||||
public static final String TODO_PLATFORM_DELETE_INSTANCE_URL = "/realDelete";
|
||||
@Inject
|
||||
private PropertiesProxy conf;
|
||||
|
||||
private String tokenUrl;
|
||||
private String todoPlatformBaseUrl;
|
||||
private String todoPlatformSaveOrUpdateUrl;
|
||||
private String todoPlatformModifyUrl;
|
||||
private String todoPlatformDeleteTaskUrl;
|
||||
private String todoPlatformDeleteInstanceUrl;
|
||||
private String todoAppId;
|
||||
private String todoAppSecret;
|
||||
private String redisKeyTodoAccessToken;
|
||||
private Long todoRequestTimeout;
|
||||
|
||||
public void init() {
|
||||
// 配置项缺失时保留原硬编码默认值,避免未补齐配置导致已有环境启动失败。
|
||||
tokenUrl = conf.get("todo-platform.token-url", "/accessToken");
|
||||
todoPlatformBaseUrl = conf.get("todo-platform.base-url", "https://gateway.jshvc.edu.cn");
|
||||
todoPlatformSaveOrUpdateUrl = conf.get("todo-platform.save-or-update-url", "/saveOrUpdate");
|
||||
todoPlatformModifyUrl = conf.get("todo-platform.modify-url", "/modifyInfo");
|
||||
todoPlatformDeleteTaskUrl = conf.get("todo-platform.delete-task-url", "/delete");
|
||||
todoPlatformDeleteInstanceUrl = conf.get("todo-platform.delete-instance-url", "/realDelete");
|
||||
todoAppId = conf.get("todo-platform.app-id", "XXXXXXXXXXXXXXXXXXXXXX");
|
||||
todoAppSecret = conf.get("todo-platform.app-secret", "XXXXXXXXXXXXXXXXXXXXXX");
|
||||
redisKeyTodoAccessToken = "todo:token:";
|
||||
todoRequestTimeout = conf.getLong("todo-platform.request-timeout", 5000L);
|
||||
}
|
||||
|
||||
public static final String TODO_APP_ID = "XXXXXXXXXXXXXXXXXXXXXX";
|
||||
public static final String TODO_APP_SECRET = "XXXXXXXXXXXXXXXXXXXXXX";
|
||||
public static final String REDIS_KEY_TODO_ACCESS_TOKEN = "todo:token:";
|
||||
public static final Long TODO_REQUEST_TIMEOUT = 5000L;
|
||||
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ public class TodoServiceImpl implements TodoService {
|
||||
private RedisService redisService;
|
||||
@Inject
|
||||
private FlowEngine flowEngine;
|
||||
@Inject
|
||||
private TodoPlatformConfig todoPlatformConfig;
|
||||
|
||||
@Override
|
||||
public void saveTask(ProcessTask task) {
|
||||
@@ -79,7 +81,7 @@ public class TodoServiceImpl implements TodoService {
|
||||
List<Processor> processorList = taskActors.stream().map(o -> new Processor(o.getActorAccount())).toList();
|
||||
|
||||
// 创建客户端
|
||||
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
|
||||
Client client = createClient();
|
||||
// 创建请求对象
|
||||
SaveOrUpdateRequest request = new SaveOrUpdateRequest();
|
||||
// 发起任务
|
||||
@@ -111,7 +113,7 @@ public class TodoServiceImpl implements TodoService {
|
||||
insertModel.setApplicationModel(applicationModel);
|
||||
request.setInsertModel(Collections.singletonList(insertModel));
|
||||
|
||||
/*Client channelClient = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
|
||||
/*Client channelClient = createClient();
|
||||
GetEnableChannelByTypeRequest channelByTypeRequest = new GetEnableChannelByTypeRequest();
|
||||
channelByTypeRequest.setChannelType(ChannelType_Constants.QYWECHAT);
|
||||
GetEnableChannelByTypeResponse channelByTypeResponse = channelClient.execute(channelByTypeRequest);
|
||||
@@ -152,7 +154,7 @@ public class TodoServiceImpl implements TodoService {
|
||||
ProcessTaskVO taskVO = flowEngine.processTaskService().findById(task.getId());
|
||||
|
||||
// 创建客户端
|
||||
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
|
||||
Client client = createClient();
|
||||
// 创建请求对象
|
||||
SaveOrUpdateRequest request = new SaveOrUpdateRequest();
|
||||
|
||||
@@ -193,7 +195,7 @@ public class TodoServiceImpl implements TodoService {
|
||||
log.info("修改待办任务,任务数据:{}", Json.toJson(task));
|
||||
try {
|
||||
// 创建客户端
|
||||
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
|
||||
Client client = createClient();
|
||||
// 创建请求对象
|
||||
TaskModifyInfoRequest request = new TaskModifyInfoRequest();
|
||||
// 需要修改什么后面扩展吧
|
||||
@@ -218,7 +220,7 @@ public class TodoServiceImpl implements TodoService {
|
||||
log.info("删除待办任务,任务ID:{}", taskId);
|
||||
try {
|
||||
// 创建客户端
|
||||
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
|
||||
Client client = createClient();
|
||||
// 创建请求对象
|
||||
TaskRealDeleteRequest request = new TaskRealDeleteRequest();
|
||||
request.setTaskId(taskId);
|
||||
@@ -240,7 +242,7 @@ public class TodoServiceImpl implements TodoService {
|
||||
log.info("删除待办流程,实例ID:{}", processInstanceId);
|
||||
try {
|
||||
// 创建客户端
|
||||
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
|
||||
Client client = createClient();
|
||||
// 创建请求对象
|
||||
ProcessInstanceRealDeleteRequest request = new ProcessInstanceRealDeleteRequest();
|
||||
request.setProcessInstanceId(processInstanceId);
|
||||
@@ -252,4 +254,15 @@ public class TodoServiceImpl implements TodoService {
|
||||
log.error("删除流程实例失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建待办平台 SDK 客户端,平台地址、appId、appSecret 均从 application 配置读取。
|
||||
*/
|
||||
private Client createClient() {
|
||||
return new DefaultClient(
|
||||
todoPlatformConfig.getTodoPlatformBaseUrl(),
|
||||
todoPlatformConfig.getTodoAppId(),
|
||||
todoPlatformConfig.getTodoAppSecret()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+23
@@ -15,6 +15,7 @@ import com.budwk.app.flow.service.FlowCommonService;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.models.ActivityReimbursementInfo;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.service.ActivityReimbursementService;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.vo.ActivityReimbursementBudgetSummaryVO;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.vo.CommonPageParam;
|
||||
import com.budwk.app.zhgh.dayofficework.outlay.activityBudget.models.ActivityBudget;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@@ -67,6 +68,7 @@ public class ActivityReimbursementDeputySchoolUnionController {
|
||||
info.userName,
|
||||
info.mobile,
|
||||
info.loginName,
|
||||
info.year,
|
||||
info.applyTime,
|
||||
info.activityName,
|
||||
info.activityAddress,
|
||||
@@ -78,6 +80,8 @@ public class ActivityReimbursementDeputySchoolUnionController {
|
||||
info.activityNumber,
|
||||
info.activityReimbursementMode,
|
||||
info.outlayManageSource,
|
||||
info.unionId,
|
||||
info.clubId,
|
||||
info.deductionBudgetId,
|
||||
info.actualMoney,
|
||||
outlay.budgetReimburseType,
|
||||
@@ -142,6 +146,25 @@ public class ActivityReimbursementDeputySchoolUnionController {
|
||||
return Result.success().addData(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("预算/报销汇总表")
|
||||
@SaCheckPermission("activityReimbursement.deputySchoolUnion")
|
||||
public Result budgetSummaryData(CommonPageParam pageParam) {
|
||||
if (pageParam.getYear() == null) {
|
||||
return Result.error("请选择年度");
|
||||
}
|
||||
if (!List.of("ACTIVITY_BUDGET_TYPE_TWO", "ACTIVITY_BUDGET_TYPE_THREE").contains(pageParam.getOutlayManageSource())) {
|
||||
return Result.error("请选择分工会或协会");
|
||||
}
|
||||
List<ActivityReimbursementBudgetSummaryVO> list = activityReimbursementService.getBudgetSummary(
|
||||
pageParam.getYear(),
|
||||
pageParam.getUnionId(),
|
||||
pageParam.getClubId(),
|
||||
pageParam.getOutlayManageSource()
|
||||
);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@SLog(tag = "报销", msg = "校工会副主席审核了一条记录")
|
||||
|
||||
+30
@@ -2,7 +2,11 @@ package com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.service;
|
||||
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.models.ActivityReimbursementInfo;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.vo.ActivityReimbursementRecordVO;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.vo.ActivityReimbursementBudgetSummaryVO;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.vo.CommonPageParam;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
@@ -34,4 +38,30 @@ public interface ActivityReimbursementService extends BaseService<ActivityReimbu
|
||||
*/
|
||||
Result bxAddValidate(String deductionBudgetId, BigDecimal moneyBig, String outlayManageSource, String clubId);
|
||||
|
||||
/**
|
||||
* 查询预算/报销汇总表。
|
||||
* @param year 汇总年度
|
||||
* @param unionId 分工会ID,分工会维度筛选时传入
|
||||
* @param clubId 协会ID,协会维度筛选时传入
|
||||
* @param outlayManageSource 经费类型,分工会传 ACTIVITY_BUDGET_TYPE_TWO,协会传 ACTIVITY_BUDGET_TYPE_THREE
|
||||
* @return 指定维度下的预算金额与已完成报销金额汇总列表
|
||||
*/
|
||||
List<ActivityReimbursementBudgetSummaryVO> getBudgetSummary(Integer year, String unionId, String clubId, String outlayManageSource);
|
||||
|
||||
/**
|
||||
* 分页查询所有已完成的费用报销记录。
|
||||
*
|
||||
* @param pageParam 查询参数,包含年度、申报人关键字、报销模式、经费类型、预算条目、分工会和协会筛选条件
|
||||
* @return 分页 VO,列表字段用于前端展示申报人、项目名称、报销模式、经费类型、预算条目、报销金额、申报单位/协会和申报时间
|
||||
*/
|
||||
Pagination<ActivityReimbursementRecordVO> queryReimbursementRecordPage(CommonPageParam pageParam);
|
||||
|
||||
/**
|
||||
* 按费用报销记录列表的同一套查询条件统计报销金额合计。
|
||||
*
|
||||
* @param pageParam 查询参数,包含年度、申报人关键字、报销模式、经费类型、预算条目、分工会和协会筛选条件
|
||||
* @return 当前查询条件下所有已完成报销记录的金额合计
|
||||
*/
|
||||
BigDecimal queryReimbursementRecordSummaryMoney(CommonPageParam pageParam);
|
||||
|
||||
}
|
||||
|
||||
+219
@@ -3,18 +3,24 @@ package com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.service.i
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.base.utils.PageUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.models.ActivityReimbursementInfo;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.reimbursement.service.ActivityReimbursementService;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.vo.ActivityReimbursementRecordVO;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.vo.ActivityReimbursementBudgetSummaryVO;
|
||||
import com.budwk.app.zhgh.activity.declarereimbursement.vo.CommonPageParam;
|
||||
import com.budwk.app.zhgh.dayofficework.outlay.activityBudget.models.ActivityBudget;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Lang;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
@@ -155,4 +161,217 @@ public class ActivityReimbursementServiceImpl extends BaseServiceImpl<ActivityRe
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActivityReimbursementBudgetSummaryVO> getBudgetSummary(Integer year, String unionId, String clubId, String outlayManageSource) {
|
||||
if (Objects.equals("ACTIVITY_BUDGET_TYPE_TWO", outlayManageSource)) {
|
||||
return getUnionBudgetSummary(year, unionId);
|
||||
}
|
||||
if (Objects.equals("ACTIVITY_BUDGET_TYPE_THREE", outlayManageSource)) {
|
||||
return getClubBudgetSummary(year, clubId);
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination<ActivityReimbursementRecordVO> queryReimbursementRecordPage(CommonPageParam pageParam) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
info.id,
|
||||
info.userName,
|
||||
info.loginName,
|
||||
info.activityName,
|
||||
info.activityReimbursementMode,
|
||||
info.outlayManageSource,
|
||||
outlay.budgetReimburseType,
|
||||
info.actualMoney,
|
||||
info.declareUnitName,
|
||||
info.applyTime,
|
||||
ins.id AS instanceId,
|
||||
ins.state AS instanceState,
|
||||
ins.processDefineId AS instanceProcessDefineId
|
||||
FROM
|
||||
activity_reimbursement_info info
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
LEFT JOIN activity_budget outlay ON outlay.id = info.deductionBudgetId
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = buildReimbursementRecordCondition(pageParam);
|
||||
String orderName = getReimbursementRecordOrderName(pageParam.getPageOrderName());
|
||||
if (StrUtil.isAllBlank(orderName, pageParam.getPageOrderBy())) {
|
||||
cnd.desc("info.applyTime");
|
||||
} else {
|
||||
cnd.orderBy(orderName, PageUtil.getOrder(pageParam.getPageOrderBy()));
|
||||
}
|
||||
sql.setCondition(cnd);
|
||||
return listPageVO(pageParam, sql, ActivityReimbursementRecordVO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal queryReimbursementRecordSummaryMoney(CommonPageParam pageParam) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
COALESCE(SUM(info.actualMoney), 0) AS summaryMoney
|
||||
FROM
|
||||
activity_reimbursement_info info
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
LEFT JOIN activity_budget outlay ON outlay.id = info.deductionBudgetId
|
||||
$condition
|
||||
""");
|
||||
sql.setCondition(buildReimbursementRecordCondition(pageParam));
|
||||
NutMap map = fetchMap(sql);
|
||||
Object summaryMoney = map.get("summaryMoney");
|
||||
return summaryMoney == null ? BigDecimal.ZERO : new BigDecimal(summaryMoney.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 前端表格排序字段白名单,避免任意字段拼接到 SQL。
|
||||
*/
|
||||
private String getReimbursementRecordOrderName(String pageOrderName) {
|
||||
if (StrUtil.isBlank(pageOrderName)) {
|
||||
return "";
|
||||
}
|
||||
if (Objects.equals("loginName", pageOrderName)) {
|
||||
return "info.loginName";
|
||||
}
|
||||
if (Objects.equals("declareUnitName", pageOrderName)) {
|
||||
return "info.declareUnitName";
|
||||
}
|
||||
if (Objects.equals("applyTime", pageOrderName)) {
|
||||
return "info.applyTime";
|
||||
}
|
||||
if (Objects.equals("actualMoney", pageOrderName)) {
|
||||
return "info.actualMoney";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 费用报销记录查询条件,列表和汇总金额共用,保证两处统计口径一致。
|
||||
*/
|
||||
private Cnd buildReimbursementRecordCondition(CommonPageParam pageParam) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("ins.state", "=", 20);
|
||||
cnd.andEX("YEAR(info.applyTime)", "=", pageParam.getYear());
|
||||
cnd.andEX("info.activityReimbursementMode", "=", pageParam.getActivityReimbursementMode());
|
||||
cnd.andEX("info.outlayManageSource", "=", pageParam.getOutlayManageSource());
|
||||
cnd.andEX("outlay.budgetReimburseType", "=", pageParam.getBudgetReimburseType());
|
||||
cnd.andEX("info.unionId", "=", pageParam.getUnionId());
|
||||
cnd.andEX("info.clubId", "=", pageParam.getClubId());
|
||||
if (StrUtil.isNotBlank(pageParam.getSearchKeyword())) {
|
||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||
seg.orLike("info.userName", pageParam.getSearchKeyword());
|
||||
seg.orLike("info.loginName", pageParam.getSearchKeyword());
|
||||
cnd.and(seg);
|
||||
}
|
||||
return cnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分工会维度汇总。
|
||||
* 预算金额取指定年度审核通过的分工会活动预算,费用报销汇总取指定年度已完成流程的报销实际金额。
|
||||
*/
|
||||
private List<ActivityReimbursementBudgetSummaryVO> getUnionBudgetSummary(Integer year, String unionId) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
@year AS year,
|
||||
su.name AS name,
|
||||
COALESCE(budget.totalBudgetMoney, 0) AS budgetMoney,
|
||||
COALESCE(reimburse.actualMoney, 0) AS reimbursementMoney
|
||||
FROM
|
||||
sys_union su
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
ab.unionId,
|
||||
SUM(ab.totalBudgetMoney) AS totalBudgetMoney
|
||||
FROM
|
||||
activity_budget ab
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = ab.id
|
||||
WHERE
|
||||
ins.state = 20
|
||||
AND ab.isSchoolBudget = 0
|
||||
AND ab.outlayManageSource = 'ACTIVITY_BUDGET_TYPE_TWO'
|
||||
AND YEAR(ab.applyDate) = @year
|
||||
GROUP BY
|
||||
ab.unionId
|
||||
) budget ON budget.unionId = su.id
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
info.unionId,
|
||||
SUM(info.actualMoney) AS actualMoney
|
||||
FROM
|
||||
activity_reimbursement_info info
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
WHERE
|
||||
ins.state = 20
|
||||
AND info.outlayManageSource = 'ACTIVITY_BUDGET_TYPE_TWO'
|
||||
AND info.`year` = @year
|
||||
GROUP BY
|
||||
info.unionId
|
||||
) reimburse ON reimburse.unionId = su.id
|
||||
$condition
|
||||
""").setParam("year", year);
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("su.id", "=", unionId);
|
||||
cnd.and(new SqlExpressionGroup()
|
||||
.or("budget.totalBudgetMoney", "is not", null)
|
||||
.or("reimburse.actualMoney", "is not", null));
|
||||
cnd.asc("su.unionCode");
|
||||
sql.setCondition(cnd);
|
||||
return listVO(sql, ActivityReimbursementBudgetSummaryVO.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 协会维度汇总。
|
||||
* 预算金额取指定年度审核通过的协会活动预算,费用报销汇总取指定年度已完成流程的报销实际金额。
|
||||
*/
|
||||
private List<ActivityReimbursementBudgetSummaryVO> getClubBudgetSummary(Integer year, String clubId) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
@year AS year,
|
||||
sc.clubName AS name,
|
||||
COALESCE(budget.totalBudgetMoney, 0) AS budgetMoney,
|
||||
COALESCE(reimburse.actualMoney, 0) AS reimbursementMoney
|
||||
FROM
|
||||
sys_club sc
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
ab.clubId,
|
||||
SUM(ab.totalBudgetMoney) AS totalBudgetMoney
|
||||
FROM
|
||||
activity_budget ab
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = ab.id
|
||||
WHERE
|
||||
ins.state = 20
|
||||
AND ab.isSchoolBudget = 0
|
||||
AND ab.outlayManageSource = 'ACTIVITY_BUDGET_TYPE_THREE'
|
||||
AND YEAR(ab.applyDate) = @year
|
||||
GROUP BY
|
||||
ab.clubId
|
||||
) budget ON budget.clubId = sc.id
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
info.clubId,
|
||||
SUM(info.actualMoney) AS actualMoney
|
||||
FROM
|
||||
activity_reimbursement_info info
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
WHERE
|
||||
ins.state = 20
|
||||
AND info.outlayManageSource = 'ACTIVITY_BUDGET_TYPE_THREE'
|
||||
AND info.`year` = @year
|
||||
GROUP BY
|
||||
info.clubId
|
||||
) reimburse ON reimburse.clubId = sc.id
|
||||
$condition
|
||||
""").setParam("year", year);
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("sc.id", "=", clubId);
|
||||
cnd.and(new SqlExpressionGroup()
|
||||
.or("budget.totalBudgetMoney", "is not", null)
|
||||
.or("reimburse.actualMoney", "is not", null));
|
||||
cnd.asc("sc.clubCode");
|
||||
sql.setCondition(cnd);
|
||||
return listVO(sql, ActivityReimbursementBudgetSummaryVO.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<configuration scan="false" scanPeriod="60000" debug="false">
|
||||
|
||||
<!-- 定义日志文件的存储路径 -->
|
||||
<!-- 日志存储路径 -->
|
||||
<property name="LOG_HOME" value="./logs"/>
|
||||
|
||||
<!-- 控制台输出配置 -->
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- INFO级别日志文件配置 -->
|
||||
|
||||
<!--
|
||||
#################################################################################
|
||||
# #
|
||||
# 全文输出日志(一个文件存储)start #
|
||||
# #
|
||||
#################################################################################
|
||||
-->
|
||||
|
||||
<!-- 所有级别日志写入同一个文件 -->
|
||||
<appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/app.log</file>
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/app-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>300</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!-- 框架日志级别(按需调整) -->
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="org.quartz" level="INFO"/>
|
||||
<logger name="org.nutz" level="DEBUG"/>
|
||||
|
||||
<!-- root logger:DEBUG 级别,输出到控制台和全量文件 -->
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="ALL_FILE"/>
|
||||
</root>
|
||||
|
||||
<!--
|
||||
#################################################################################
|
||||
# #
|
||||
# 全文输出日志(一个文件存储)end #
|
||||
# #
|
||||
#################################################################################
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
#################################################################################
|
||||
# #
|
||||
# debug、info、error分文件输出 start #
|
||||
# #
|
||||
#################################################################################
|
||||
-->
|
||||
|
||||
<!-- DEBUG级别日志文件配置 -->
|
||||
<!--<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/debug.log</file>
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>DEBUG</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/debug-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>300</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!– INFO级别日志文件配置 –>
|
||||
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/info.log</file>
|
||||
<encoder>
|
||||
@@ -24,11 +92,11 @@
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/info-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>30</maxHistory>
|
||||
<maxHistory>300</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!-- ERROR级别日志文件配置 -->
|
||||
<!– ERROR级别日志文件配置 –>
|
||||
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/error.log</file>
|
||||
<encoder>
|
||||
@@ -41,19 +109,31 @@
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/error-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>30</maxHistory>
|
||||
<maxHistory>300</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<logger name="java" additivity="false" />
|
||||
<!– 框架日志级别 –>
|
||||
<!– <logger name="java" additivity="false" />–>
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="org.quartz" level="INFO"/>
|
||||
<logger name="org.nutz" level="DEBUG"/>
|
||||
|
||||
<!-- 日志级别和appender的关联 -->
|
||||
<!– 日志级别和appender的关联 –>
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="DEBUG_FILE"/>
|
||||
<appender-ref ref="INFO_FILE"/>
|
||||
<appender-ref ref="ERROR_FILE"/>
|
||||
</root>
|
||||
</root>-->
|
||||
|
||||
<!--
|
||||
#################################################################################
|
||||
# #
|
||||
# debug、info、error分文件输出 end #
|
||||
# #
|
||||
#################################################################################
|
||||
-->
|
||||
|
||||
</configuration>
|
||||
|
||||
|
||||
+143
-1
@@ -64,6 +64,7 @@ layout("/layouts/platform.html"){
|
||||
<el-radio-button label="true">已审核</el-radio-button>
|
||||
<el-radio-button label="false">未审核</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-button @click="openBudgetSummary" size="small" type="primary">预算/报销汇总表</el-button>
|
||||
</table-tool>
|
||||
|
||||
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder"
|
||||
@@ -94,6 +95,10 @@ layout("/layouts/platform.html"){
|
||||
<template scope="{row}" v-else-if="column.prop=='activityReimbursementMode'">
|
||||
<span>{{ row.activityReimbursementMode==='activity'?'活动报销' : '日常报销' }}</span>
|
||||
</template>
|
||||
<template scope="{row}" v-else-if="column.prop=='declareUnitName'">
|
||||
<el-link @click="openUnitSummary(row)" type="primary" v-if="canOpenUnitSummary(row)">{{row.declareUnitName}}</el-link>
|
||||
<span v-else>{{row.declareUnitName}}</span>
|
||||
</template>
|
||||
<template scope="{row}" v-else-if="column.prop=='instanceState'">
|
||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
|
||||
size="small"></enum-tag>
|
||||
@@ -112,6 +117,58 @@ layout("/layouts/platform.html"){
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<el-dialog :visible.sync="summaryDialogVisible" title="预算/报销汇总表" width="760px">
|
||||
<el-form :inline="true" :model="summaryForm" size="small">
|
||||
<el-form-item label="年度">
|
||||
<el-date-picker
|
||||
:clearable="false"
|
||||
placeholder="请选择年度"
|
||||
type="year"
|
||||
v-model="summaryForm.year"
|
||||
value-format="yyyy">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型">
|
||||
<el-radio-group @change="summaryTypeChange" v-model="summaryForm.outlayManageSource">
|
||||
<el-radio-button label="ACTIVITY_BUDGET_TYPE_TWO">分工会</el-radio-button>
|
||||
<el-radio-button label="ACTIVITY_BUDGET_TYPE_THREE">协会</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="分工会" v-if="summaryForm.outlayManageSource === 'ACTIVITY_BUDGET_TYPE_TWO'">
|
||||
<el-select clearable filterable placeholder="请选择分工会" style="width: 180px;"
|
||||
v-model="summaryForm.unionId">
|
||||
<el-option :label="item.name" :value="item.id" v-for="item in unions"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="协会" v-if="summaryForm.outlayManageSource === 'ACTIVITY_BUDGET_TYPE_THREE'">
|
||||
<el-select clearable filterable placeholder="请选择协会" style="width: 180px;"
|
||||
v-model="summaryForm.clubId">
|
||||
<el-option :label="item.clubName" :value="item.id" v-for="item in clubs"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="getBudgetSummary" type="primary">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="summaryData" border style="width: 100%" v-loading="summaryLoading">
|
||||
<el-table-column align="center" label="序号" type="index" width="70"></el-table-column>
|
||||
<el-table-column align="center" label="年度" prop="year" width="100"></el-table-column>
|
||||
<el-table-column :label="summaryNameLabel" prop="name"></el-table-column>
|
||||
<el-table-column align="right" label="预算金额" prop="budgetMoney" width="150"></el-table-column>
|
||||
<el-table-column align="right" label="费用报销汇总" prop="reimbursementMoney" width="160"></el-table-column>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :visible.sync="unitSummaryDialogVisible" title="申报单位/协会汇总" width="720px">
|
||||
<el-table :data="unitSummaryData" border style="width: 100%" v-loading="unitSummaryLoading">
|
||||
<el-table-column align="center" label="年度" prop="year" width="100"></el-table-column>
|
||||
<el-table-column align="center" :label="unitSummaryNameLabel" prop="name"></el-table-column>
|
||||
<el-table-column align="right" label="年度预算" prop="budgetMoney" width="140"></el-table-column>
|
||||
<el-table-column align="right" label="年度报销" prop="reimbursementMoney" width="140"></el-table-column>
|
||||
<el-table-column align="right" label="本次报销" prop="currentReimbursementMoney" width="140"></el-table-column>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
|
||||
<template #edit>
|
||||
<info ref="infoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
@@ -174,13 +231,98 @@ layout("/layouts/platform.html"){
|
||||
|
||||
// 审核相关
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
showApprovalForm: false,
|
||||
|
||||
// 预算/报销汇总弹框。year 查询年度;outlayManageSource 为汇总维度;unionId/clubId 为对应维度筛选条件。
|
||||
summaryDialogVisible: false,
|
||||
summaryLoading: false,
|
||||
summaryData: [],
|
||||
summaryForm: {
|
||||
year: this.$moment().format("YYYY"),
|
||||
outlayManageSource: "ACTIVITY_BUDGET_TYPE_TWO",
|
||||
unionId: "",
|
||||
clubId: ""
|
||||
},
|
||||
|
||||
// 列表行申报单位/协会汇总弹框。点击列表单位名称时,按当前行的年度、经费类型、分工会或协会 ID 查询。
|
||||
unitSummaryDialogVisible: false,
|
||||
unitSummaryLoading: false,
|
||||
unitSummaryNameLabel: "分工会",
|
||||
unitSummaryData: []
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'info': INFO,
|
||||
},
|
||||
computed: {
|
||||
summaryNameLabel() {
|
||||
return this.summaryForm.outlayManageSource === "ACTIVITY_BUDGET_TYPE_TWO" ? "分工会" : "协会"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openBudgetSummary() {
|
||||
this.$set(this.summaryForm, "year", this.pageForm.year || this.$moment().format("YYYY"))
|
||||
this.$set(this, "summaryDialogVisible", true)
|
||||
this.getBudgetSummary()
|
||||
},
|
||||
summaryTypeChange(val) {
|
||||
this.$set(this.summaryForm, "unionId", "")
|
||||
this.$set(this.summaryForm, "clubId", "")
|
||||
this.$set(this.summaryForm, "outlayManageSource", val)
|
||||
this.getBudgetSummary()
|
||||
},
|
||||
getBudgetSummary() {
|
||||
this.summaryLoading = true
|
||||
this.$axios.post("/platform/activityReimbursement/deputySchoolUnion/budgetSummaryData", this.summaryForm)
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "summaryData", res.data || [])
|
||||
} else {
|
||||
this.$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.summaryLoading = false
|
||||
})
|
||||
},
|
||||
canOpenUnitSummary(row) {
|
||||
return (row.outlayManageSource === "ACTIVITY_BUDGET_TYPE_TWO" && row.unionId)
|
||||
|| (row.outlayManageSource === "ACTIVITY_BUDGET_TYPE_THREE" && row.clubId)
|
||||
},
|
||||
openUnitSummary(row) {
|
||||
if (row.outlayManageSource !== "ACTIVITY_BUDGET_TYPE_TWO" && row.outlayManageSource !== "ACTIVITY_BUDGET_TYPE_THREE") {
|
||||
this.$message.warning("仅支持查看分工会或协会汇总")
|
||||
return
|
||||
}
|
||||
if (row.outlayManageSource === "ACTIVITY_BUDGET_TYPE_TWO" && !row.unionId) {
|
||||
this.$message.warning("当前数据缺少分工会信息")
|
||||
return
|
||||
}
|
||||
if (row.outlayManageSource === "ACTIVITY_BUDGET_TYPE_THREE" && !row.clubId) {
|
||||
this.$message.warning("当前数据缺少协会信息")
|
||||
return
|
||||
}
|
||||
this.$set(this, "unitSummaryDialogVisible", true)
|
||||
this.$set(this, "unitSummaryLoading", true)
|
||||
this.$set(this, "unitSummaryNameLabel", row.outlayManageSource === "ACTIVITY_BUDGET_TYPE_TWO" ? "分工会" : "协会")
|
||||
this.$axios.post("/platform/activityReimbursement/deputySchoolUnion/budgetSummaryData", {
|
||||
year: row.year || this.pageForm.year || this.$moment().format("YYYY"),
|
||||
outlayManageSource: row.outlayManageSource,
|
||||
unionId: row.outlayManageSource === "ACTIVITY_BUDGET_TYPE_TWO" ? row.unionId : "",
|
||||
clubId: row.outlayManageSource === "ACTIVITY_BUDGET_TYPE_THREE" ? row.clubId : ""
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "unitSummaryData", (res.data || []).map((item) => {
|
||||
this.$set(item, "currentReimbursementMoney", row.actualMoney)
|
||||
return item
|
||||
}))
|
||||
} else {
|
||||
this.$message.error(res.msg)
|
||||
}
|
||||
}).finally(() => {
|
||||
this.unitSummaryLoading = false
|
||||
})
|
||||
},
|
||||
openView(row) {
|
||||
this.$refs.guava.edit(() => {
|
||||
this.showApprovalForm = false
|
||||
|
||||
Reference in New Issue
Block a user