@@ -0,0 +1,281 @@
package xiaoqu.home.open.constant ;
import java.math.BigDecimal ;
import java.math.RoundingMode ;
import java.util.Arrays ;
import java.util.Collections ;
import java.util.HashSet ;
import java.util.Set ;
/**
* 业务规则注册表.
*
* 所有核心业务规则在此集中定义,作为系统业务逻辑的"单一事实来源"。
*
* [PROTECTED] 此文件为红区文件, AI 不可直接修改。
* 修改需审批人:项目经理 + 技术负责人。
*
* 使用方式:
* 1. 业务代码中引用此处常量,禁止硬编码业务规则值
* 2. 系统启动时调用 validateAll() 校验规则完整性
* 3. 新增业务规则须同步添加校验方法和单元测试
*
* @author SmartClean Team
* @since 2026-04-15
*/
public final class BusinessRules {
private BusinessRules ( ) {
throw new UnsupportedOperationException ( " 常量类不可实例化 " ) ;
}
// =====================================================================
// 一、工资计算规则 (BR-SALARY)
// =====================================================================
/** BR-SALARY-001: 法定月计薪天数(劳动法规定) */
public static final BigDecimal MONTHLY_WORK_DAYS = new BigDecimal ( " 21.75 " ) ;
/** BR-SALARY-002: 平日加班费率( 1.5 倍) */
public static final BigDecimal WEEKDAY_OVERTIME_RATE = new BigDecimal ( " 1.5 " ) ;
/** BR-SALARY-003: 周末加班费率( 2.0 倍) */
public static final BigDecimal WEEKEND_OVERTIME_RATE = new BigDecimal ( " 2.0 " ) ;
/** BR-SALARY-004: 法定假日加班费率( 3.0 倍) */
public static final BigDecimal HOLIDAY_OVERTIME_RATE = new BigDecimal ( " 3.0 " ) ;
/** BR-SALARY-005: 标准日工作时长(小时) */
public static final BigDecimal STANDARD_DAILY_WORK_HOURS = new BigDecimal ( " 8 " ) ;
/** BR-SALARY-006: 工资金额计算精度(小数位数) */
public static final int SALARY_SCALE = 2 ;
/** BR-SALARY-007: 工资金额舍入模式(四舍五入) */
public static final RoundingMode SALARY_ROUNDING = RoundingMode . HALF_UP ;
/** BR-SALARY-008: 最低工资标准(元/月),按当地政策设定,需定期更新 */
public static final BigDecimal MINIMUM_MONTHLY_WAGE = new BigDecimal ( " 2690.00 " ) ;
// =====================================================================
// 二、打卡考勤规则 (BR-ATTEND)
// =====================================================================
/** BR-ATTEND-001: 打卡地理围栏默认半径(米) */
public static final int DEFAULT_FENCE_RADIUS_METERS = 200 ;
/** BR-ATTEND-002: 防重复打卡时间窗口(分钟),同类型打卡在此时间内不可重复 */
public static final int DUPLICATE_PUNCH_WINDOW_MINUTES = 30 ;
/** BR-ATTEND-003: 迟到判定阈值(分钟),超过排班开始时间此值算迟到 */
public static final int LATE_THRESHOLD_MINUTES = 15 ;
/** BR-ATTEND-004: 早退判定阈值(分钟),早于排班结束时间此值算早退 */
public static final int EARLY_LEAVE_THRESHOLD_MINUTES = 15 ;
/** BR-ATTEND-005: 严重迟到阈值(分钟),超过此值算严重迟到 */
public static final int SEVERE_LATE_THRESHOLD_MINUTES = 60 ;
/** BR-ATTEND-006: 旷工判定阈值(分钟),超过此值未打卡算旷工 */
public static final int ABSENT_THRESHOLD_MINUTES = 120 ;
/** BR-ATTEND-007: GPS 定位超时时间(秒) */
public static final int GPS_TIMEOUT_SECONDS = 15 ;
/** BR-ATTEND-008: WiFi 辅助定位允许的最大偏差(米) */
public static final int WIFI_LOCATION_MAX_DEVIATION_METERS = 100 ;
/** BR-ATTEND-009: 只允许本人打卡,不可代打 */
public static final boolean SELF_PUNCH_ONLY = true ;
/** BR-ATTEND-010: 打卡记录保留期限(天),超过此期限的记录可归档 */
public static final int PUNCH_RECORD_RETENTION_DAYS = 365 ;
// =====================================================================
// 三、排班规则 (BR-SCHED)
// =====================================================================
/** BR-SCHED-001: 单人单日最大排班时长(小时) */
public static final int MAX_DAILY_SCHEDULE_HOURS = 12 ;
/** BR-SCHED-002: 两个排班之间最小休息时间(小时) */
public static final int MIN_REST_HOURS_BETWEEN_SHIFTS = 8 ;
/** BR-SCHED-003: 排班交接重叠容差(分钟),此范围内不算冲突 */
public static final int SCHEDULE_HANDOVER_TOLERANCE_MINUTES = 0 ;
/** BR-SCHED-004: 排班提前发布天数,排班表至少提前此天数发布 */
public static final int SCHEDULE_PUBLISH_ADVANCE_DAYS = 3 ;
/** BR-SCHED-005: 单人单周最大排班天数 */
public static final int MAX_WEEKLY_SCHEDULE_DAYS = 6 ;
/** BR-SCHED-006: 夜班定义起始时间( 24 小时制) */
public static final int NIGHT_SHIFT_START_HOUR = 22 ;
/** BR-SCHED-007: 夜班定义结束时间( 24 小时制) */
public static final int NIGHT_SHIFT_END_HOUR = 6 ;
// =====================================================================
// 四、任务管理规则 (BR-TASK)
// =====================================================================
/** BR-TASK-001: 任务超时告警阈值(分钟),超过预计时长此值后触发告警 */
public static final int TASK_OVERTIME_ALERT_MINUTES = 30 ;
/** BR-TASK-002: 任务照片最少数量,完成任务时至少需上传此数量的照片 */
public static final int TASK_MIN_PHOTO_COUNT = 1 ;
/** BR-TASK-003: 任务照片最大数量 */
public static final int TASK_MAX_PHOTO_COUNT = 9 ;
/** BR-TASK-004: 任务评分满分 */
public static final int TASK_MAX_SCORE = 100 ;
/** BR-TASK-005: 任务合格分数线 */
public static final int TASK_PASS_SCORE = 60 ;
// =====================================================================
// 五、巡检规则 (BR-PATROL)
// =====================================================================
/** BR-PATROL-001: 巡检点最小停留时间(秒),少于此时间判定为无效巡检 */
public static final int PATROL_MIN_STAY_SECONDS = 30 ;
/** BR-PATROL-002: 巡检轨迹记录间隔(秒) */
public static final int PATROL_TRACK_INTERVAL_SECONDS = 10 ;
/** BR-PATROL-003: 巡检异常自动上报,发现异常时自动生成工单 */
public static final boolean PATROL_AUTO_REPORT_ANOMALY = true ;
// =====================================================================
// 六、系统通用规则 (BR-SYS)
// =====================================================================
/** BR-SYS-001: 分页查询每页最大条数 */
public static final int MAX_PAGE_SIZE = 100 ;
/** BR-SYS-002: 分页查询默认每页条数 */
public static final int DEFAULT_PAGE_SIZE = 20 ;
/** BR-SYS-003: 数据删除方式 — 逻辑删除标记值( 0=未删除, 1=已删除) */
public static final int DELETED_FLAG = 1 ;
public static final int NOT_DELETED_FLAG = 0 ;
/** BR-SYS-004: 批量操作最大条数 */
public static final int MAX_BATCH_SIZE = 500 ;
/** BR-SYS-005: 导出 Excel 最大行数 */
public static final int MAX_EXPORT_ROWS = 10000 ;
/** BR-SYS-006: 文件上传最大大小( MB) */
public static final int MAX_UPLOAD_SIZE_MB = 20 ;
/** BR-SYS-007: 允许上传的图片格式 */
public static final Set < String > ALLOWED_IMAGE_FORMATS = Collections . unmodifiableSet (
new HashSet < > ( Arrays . asList ( " jpg " , " jpeg " , " png " , " bmp " , " gif " ) ) ) ;
// =====================================================================
// 七、龙虾助手/对话交互规则 (BR-CHAT)
// =====================================================================
/** BR-CHAT-001: 写操作需要二次确认 */
public static final boolean WRITE_OPERATION_REQUIRES_CONFIRM = true ;
/** BR-CHAT-002: 闲聊不触发任何数据库操作 */
public static final boolean CHITCHAT_NO_DB_OPERATION = true ;
/** BR-CHAT-003: 危险操作(删除/修改工资/修改权限)通过对话禁止执行 */
public static final boolean DANGEROUS_OPERATION_BLOCKED_VIA_CHAT = true ;
// =====================================================================
// 规则校验方法
// =====================================================================
/**
* 校验所有业务规则完整性.
* 建议在系统启动时调用,确保核心常量未被篡改。
*
* @throws AssertionError 如果任何规则被篡改
*/
public static void validateAll ( ) {
validateSalaryRules ( ) ;
validateAttendanceRules ( ) ;
validateScheduleRules ( ) ;
validateSystemRules ( ) ;
}
/**
* 校验工资计算规则.
*/
public static void validateSalaryRules ( ) {
assertRule ( MONTHLY_WORK_DAYS . compareTo ( new BigDecimal ( " 21.75 " ) ) = = 0 ,
" BR-SALARY-001 " , " 月计薪天数 " , " 21.75 " , MONTHLY_WORK_DAYS . toString ( ) ) ;
assertRule ( WEEKDAY_OVERTIME_RATE . compareTo ( new BigDecimal ( " 1.5 " ) ) = = 0 ,
" BR-SALARY-002 " , " 平日加班费率 " , " 1.5 " , WEEKDAY_OVERTIME_RATE . toString ( ) ) ;
assertRule ( WEEKEND_OVERTIME_RATE . compareTo ( new BigDecimal ( " 2.0 " ) ) = = 0 ,
" BR-SALARY-003 " , " 周末加班费率 " , " 2.0 " , WEEKEND_OVERTIME_RATE . toString ( ) ) ;
assertRule ( HOLIDAY_OVERTIME_RATE . compareTo ( new BigDecimal ( " 3.0 " ) ) = = 0 ,
" BR-SALARY-004 " , " 法定假日加班费率 " , " 3.0 " , HOLIDAY_OVERTIME_RATE . toString ( ) ) ;
assertRule ( STANDARD_DAILY_WORK_HOURS . compareTo ( new BigDecimal ( " 8 " ) ) = = 0 ,
" BR-SALARY-005 " , " 标准日工作时长 " , " 8 " , STANDARD_DAILY_WORK_HOURS . toString ( ) ) ;
assertRule ( SALARY_SCALE = = 2 ,
" BR-SALARY-006 " , " 工资精度 " , " 2 " , String . valueOf ( SALARY_SCALE ) ) ;
assertRule ( SALARY_ROUNDING = = RoundingMode . HALF_UP ,
" BR-SALARY-007 " , " 舍入模式 " , " HALF_UP " , SALARY_ROUNDING . toString ( ) ) ;
}
/**
* 校验打卡考勤规则.
*/
public static void validateAttendanceRules ( ) {
assertRule ( DEFAULT_FENCE_RADIUS_METERS = = 200 ,
" BR-ATTEND-001 " , " 围栏半径 " , " 200 " , String . valueOf ( DEFAULT_FENCE_RADIUS_METERS ) ) ;
assertRule ( DUPLICATE_PUNCH_WINDOW_MINUTES = = 30 ,
" BR-ATTEND-002 " , " 防重窗口 " , " 30 " , String . valueOf ( DUPLICATE_PUNCH_WINDOW_MINUTES ) ) ;
assertRule ( LATE_THRESHOLD_MINUTES = = 15 ,
" BR-ATTEND-003 " , " 迟到阈值 " , " 15 " , String . valueOf ( LATE_THRESHOLD_MINUTES ) ) ;
assertRule ( EARLY_LEAVE_THRESHOLD_MINUTES = = 15 ,
" BR-ATTEND-004 " , " 早退阈值 " , " 15 " , String . valueOf ( EARLY_LEAVE_THRESHOLD_MINUTES ) ) ;
assertRule ( SELF_PUNCH_ONLY ,
" BR-ATTEND-009 " , " 本人打卡 " , " true " , String . valueOf ( SELF_PUNCH_ONLY ) ) ;
}
/**
* 校验排班规则.
*/
public static void validateScheduleRules ( ) {
assertRule ( MAX_DAILY_SCHEDULE_HOURS = = 12 ,
" BR-SCHED-001 " , " 单日最大排班时长 " , " 12 " , String . valueOf ( MAX_DAILY_SCHEDULE_HOURS ) ) ;
assertRule ( MIN_REST_HOURS_BETWEEN_SHIFTS = = 8 ,
" BR-SCHED-002 " , " 最小休息时间 " , " 8 " , String . valueOf ( MIN_REST_HOURS_BETWEEN_SHIFTS ) ) ;
assertRule ( MAX_WEEKLY_SCHEDULE_DAYS = = 6 ,
" BR-SCHED-005 " , " 单周最大排班天数 " , " 6 " , String . valueOf ( MAX_WEEKLY_SCHEDULE_DAYS ) ) ;
}
/**
* 校验系统通用规则.
*/
public static void validateSystemRules ( ) {
assertRule ( MAX_PAGE_SIZE = = 100 ,
" BR-SYS-001 " , " 最大分页条数 " , " 100 " , String . valueOf ( MAX_PAGE_SIZE ) ) ;
assertRule ( DELETED_FLAG = = 1 ,
" BR-SYS-003 " , " 逻辑删除标记 " , " 1 " , String . valueOf ( DELETED_FLAG ) ) ;
assertRule ( NOT_DELETED_FLAG = = 0 ,
" BR-SYS-003 " , " 未删除标记 " , " 0 " , String . valueOf ( NOT_DELETED_FLAG ) ) ;
assertRule ( MAX_BATCH_SIZE = = 500 ,
" BR-SYS-004 " , " 批量操作上限 " , " 500 " , String . valueOf ( MAX_BATCH_SIZE ) ) ;
}
/**
* 断言业务规则.
*/
private static void assertRule ( boolean condition , String ruleId , String ruleName ,
String expectedValue , String actualValue ) {
if ( ! condition ) {
throw new AssertionError ( String . format (
" 业务规则被篡改![%s] %s: 期望=%s, 实际=%s " ,
ruleId , ruleName , expectedValue , actualValue ) ) ;
}
}
}