Files
ERP/oa-backend/src/main/java/com/kaidi/oa/common/MoneyParser.java
T
QiufengandClaude Opus 4.8 5e51dc3f56 SNAPSHOT W7 已部署稳定态 — 凯迪ERP+OA一体化平台 (MET 73.3%)
恢复点(restore point)。别人改崩后可 git reset --hard 回到此提交。

== 此快照内容 ==
- 后端 oa-backend: 734 控制器 / 711 实体 (Spring Boot 3.2.5 + SQLite, 端口8091)
- 前端 modern-ui/app: Vue3+Vite, 约700页 (构建产物已在 oa-backend/src/main/resources/static)
- 数据库 oa-backend/data/oa.db: 含全部演示数据 (强制入库, 6.6MB)
- 交接文档 go.md + go-code-reference/endpoints/entities/database.md
- 多代理建设脚本 .claude/wf-*.js

== 状态 ==
- 对 凯迪科技ERP_20260507.xlsx 合规 MET ~73.3% (PARTIAL 75: 34可建+6种子/bug+35外部硬天花板)
- 安全: 5轮红队+5轮复检, default-deny分级鉴权, 连续零可利用
- W3~W7 累计补完436缺口; W8末轮(40缺口)为半成品(源码树可编译但未集成)
- 运行: cd oa-backend; java -jar build/libs/oa-backend-0.1.0.jar --server.port=8091; admin/123456

== 排除(gitignore, 可再生) ==
node_modules / oa-backend/build / .jdks / *.log / Backup-ERP-* / 弃用的OFBiz核心(只保留modern-ui)
完整文件夹备份见同目录 Backup-ERP-20260615-191517/ (含上述全部, 仅缺 node_modules)

时间戳: 20260615-191517

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 19:19:15 +08:00

68 lines
3.1 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.kaidi.oa.common;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 金额文本解析收口(BigDecimal-native)。
*
* <p>历史上 {@code TriggerRuleEngine.parseNumber} / {@code WorkflowService.parseNumber} /
* {@code MobileApprovalController.parseNumber} 三处各自手写了一份"剥噪声→{@code Double.parseDouble}"
* 的金额解析,返回裸 {@code double}:自动联动据此生成付款单/发票,金额下游与台账留痕里就会冒出
* {@code 5.07}、{@code 9.9999999997} 这类二进制浮点伪值(如 5000万经 JSON 序列化为 "5.0E7",或
* 表单 "10.00" 累加后抖动)。本工具把"解析"这一步直接落到 {@link BigDecimal},杜绝中途经过 double
* 用 {@link BigDecimal#BigDecimal(String)}(字符串构造,精确)而非 {@code Double.parseDouble}
* 再统一 {@code setScale(2, HALF_UP)} 规整成"分"标度,使解析结果与 {@link Money} 完全同口径。</p>
*
* <p>容噪规则与原三处保持一致:剥掉 ¥/¥/元/逗号/空白等装饰字符,<b>保留</b> 数字、小数点、正负号
* 与科学计数标记 {@code e/E}(大额金额经 JSON 常序列化为 "5.0E7",剥掉 E 会把它错解析成 5.07,
* 量级灾难);末尾带「万」整体 ×10000。无法解析时返回 {@code null}(业务侧据此走"未解析到金额→跳过")。</p>
*/
public final class MoneyParser {
private static final BigDecimal TEN_THOUSAND = new BigDecimal("10000");
private MoneyParser() {
}
/**
* 解析金额文本 → 标度 2、HALF_UP 的 {@link BigDecimal};解析失败返回 {@code null}。
*
* <p>关键:用 {@code new BigDecimal(cleaned)}(字符串精确构造,支持科学计数法),<b>绝不</b>
* 走 {@code Double.parseDouble},故 "5.0E7"→50000000.00、"10.00"→10.00 全程无浮点抖动。</p>
*/
public static BigDecimal parse(String raw) {
if (raw == null) {
return null;
}
String s = raw.trim();
if (s.isEmpty()) {
return null;
}
boolean wan = s.contains("万");
// 保留 0-9 . e E + - ,剥掉其余(¥ 元 万 千分位逗号 空白…)。务必保留 e/E:科学计数法大额。
String cleaned = s.replaceAll("[^0-9.eE+-]", "");
if (cleaned.isEmpty() || "+".equals(cleaned) || "-".equals(cleaned) || ".".equals(cleaned)) {
return null;
}
try {
BigDecimal v = new BigDecimal(cleaned);
if (wan) {
v = v.multiply(TEN_THOUSAND);
}
return v.setScale(Money.SCALE, RoundingMode.HALF_UP);
} catch (NumberFormatException e) {
return null;
}
}
/**
* 同 {@link #parse(String)},但解析失败回退为 {@link Money#ZERO}(标度 2 的 0.00)。
* 适合"展示/排序用金额,缺失即按 0 处理且不抛错"的场景(如移动待办列表金额列)。
*/
public static BigDecimal parseOrZero(String raw) {
BigDecimal v = parse(raw);
return v == null ? Money.ZERO : v;
}
}