package com.ruoyi.project.common; import com.ruoyi.common.enums.ApplyTypeEnum; import com.ruoyi.common.utils.StringUtils; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.ConcurrentHashMap; /** * 报销审批钉钉消息内容组装。 * *
统一「标题 + 单据信息 + 审批意见文案」,供以下发送点复用: *
为什么要一行一个 map:{@code DingTalkReqVo.contents} 的元素是
* {@link ConcurrentHashMap},其遍历顺序不保证;一条 map 里塞多行会导致钉钉表单行序错乱。
* 这里每条信息单独一个「单键 map」,用 List 的顺序保证显示顺序。
*
* @author ruoyi
*/
public final class FundNotifyMessageBuilder {
/** 钉钉消息统一标题(2026-10-08 业务方确认统一为「OPO报销审批」) */
public static final String TITLE = "OPO报销审批";
/** 审批结论:通过 */
public static final String CONCLUSION_PASS = "1";
/** 审批结论:驳回 */
public static final String CONCLUSION_REJECT = "2";
/** 审批结论:完结 */
public static final String CONCLUSION_FINISH = "3";
private static final String KEY_TYPE = "报销单类型:";
private static final String KEY_BENEFICIARY = "报销人:";
private static final String KEY_AMOUNT = "金额:";
private static final String KEY_DONOR = "捐献案例:";
private static final String KEY_BILL_NO = "单据编号:";
private static final String KEY_TRAVELERS = "出差人:";
private static final String KEY_REASON = "出差事由:";
private static final String KEY_CHECKER = "审批人:";
private static final String KEY_CHECK_TIME = "审批时间:";
private static final String KEY_OPINION = "意见:";
private static final String KEY_SUBMITTER = "提交人:";
private static final String KEY_SUBMIT_TIME = "提交时间:";
private static final String KEY_CONTENT = "内容:";
private FundNotifyMessageBuilder() {
}
/** 新建内容行容器 */
public static List 金额口径:费用类取 {@code service_fund.pretaxcost}(审核页「申请金额」列),
* 差旅费取 {@code service_reimbursement.amountrequested}(审核页「报销金额」列)。
*/
public static void addBillInfo(List 审批时间传 {@link Date}:键名含「审批时间」,由 {@code DingTalkServiceImpl} 统一格式化。
*/
public static void addAuditResult(List 实测依据(本地库 {@code service_fundflow.flowlevel=100} 即致远回传记录):
* 通过 11618 条中 9606 条意见为空、完结 1457 条全部为空、驳回 743 条中 161 条为空。
* 若不给结论兜底文案,钉钉消息的「意见」一栏就是空白(这正是业务反馈的问题)。
*/
public static String opinion(String conclusion, String content) {
String remark = content == null ? "" : content.trim();
String base;
if (CONCLUSION_PASS.equals(conclusion)) {
base = "审批通过。";
} else if (CONCLUSION_REJECT.equals(conclusion)) {
base = "审批未通过。";
} else if (CONCLUSION_FINISH.equals(conclusion)) {
base = "流程已完结。";
} else {
// 结论缺失:只显示备注,不臆测结论
return remark;
}
return remark.isEmpty() ? base : base + remark;
}
/** 金额显示:两位小数、无千分位,如 {@code 1200.00 元} */
public static String money(Double amount) {
if (amount == null) {
return null;
}
return new BigDecimal(String.valueOf(amount))
.setScale(2, RoundingMode.HALF_UP)
.toPlainString() + " 元";
}
/** 时间显示:{@code yyyy-MM-dd HH:mm:ss}(24 小时制) */
public static String time(Date date) {
return date == null ? null : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
}
}
* 通过(1) → "审批通过。" + 意见备注(若有)
* 驳回(2) → "审批未通过。" + 意见备注(若有)
* 完结(3) → "流程已完结。"
* 其他/空 → 原样返回备注;无备注返回空串
*
*
*