fujian_water_biz_doc/water_biz_module_design.md

44 KiB
Raw Blame History

福建水务营收系统模块功能设计文档

文档信息

项目信息 详情
项目名称 福建水务营收系统
文档类型 概要设计文档
技术框架 RuoYi-Vue-Pro + yudao-ui-admin-vue3
文档版本 v1.0
编写日期 2024-12-19
文档状态 🟡 进行中

目录

1. 统一平台

统一平台是客户服务平台的综合展示平台基于RuoYi-Vue-Pro和yudao-ui-admin-vue3框架构建包含日常工作功能和客户全部的信息是系统的基础功能模块。

1.1 单点登录

单点登录模块基于Spring Security和JWT实现用户一次登录即可访问系统中所有应用的功能主要特点包括

  • 支持通过用户名、密码进行身份认证
  • 支持OAuth2.0授权码+PKCE模式的第三方登录
  • 支持手机号+短信验证码登录方式
  • 支持多因素认证MFA增强安全性
  • 根据登录人员所在公司的不同,显示不同的系统名称和界面风格
  • 提供流程节点到期提醒功能
  • Token自动刷新机制提升用户体验

1.2 系统管理

系统管理模块基于RuoYi-Vue-Pro框架的现成功能提供对系统基础参数的配置管理功能主要包括

  • 组织机构管理:
    • 支持多级组织结构的管理
    • 支持组织机构导入导出
    • 组织关系树形展示
    • 组织数据权限控制
  • 员工管理:
    • 系统操作人员的基本信息管理
    • 用户分配角色与权限
    • 用户状态管理(启用/禁用)
    • 用户密码安全策略
    • 用户操作日志记录
  • 角色权限管理:
    • 基于RBAC模型的权限控制
    • 支持数据权限精细化控制
    • 支持多租户的权限隔离
    • 基于菜单、按钮级别的权限管理
  • 系统菜单配置:
    • 支持自定义系统菜单和功能模块
    • 菜单多级分类管理
    • 动态路由生成
    • 菜单权限配置
  • 数据字典管理:
    • 维护系统使用的各类基础代码数据
    • 支持字典项多级管理
    • 支持字典缓存,提高访问性能
  • 系统监控:
    • 在线用户监控与管理
    • 服务器性能监控
    • 定时任务执行状态监控
    • 系统缓存监控与管理
  • 系统日志管理:
    • 记录用户登录日志
    • 记录操作日志,支持操作回溯
    • 记录系统异常日志,便于问题排查
  • 短信管理:
    • 支持阿里云、腾讯云等多家短信渠道
    • 短信模板配置管理
    • 短信发送日志记录
  • 租户管理:
    • 支持SaaS多租户
    • 租户套餐配置
    • 租户数据隔离
    • 租户资源管理
  • 配置管理:
    • 系统参数配置
    • 通知公告管理
    • 定时任务配置

2. 营收系统

营收系统是水务业务系统的核心组成部分,负责抄表、收费、账务处理等关键业务功能。

2.1 系统管理

营收系统的基础管理功能,包括:

  • 水价管理:不同用户类型的水价标准管理,支持阶梯水价
  • 用户档案管理:维护用户基本信息、用水信息、账户信息等
    • 客户分组管理
    • 集收管理
    • 客户基础信息管理
    • 定额管理
    • 客户优惠方案设置
  • 更名过户管理:处理用户变更、过户等业务
  • 注销报停管理:处理用户注销、暂停用水等业务

2.2 抄表开账

抄表开账模块负责水表读数的采集和账单生成,是营收系统的核心业务模块。

2.2.1 业务流程图

flowchart TD
    Start([开始抄表周期]) --> BookPlan[制定抄表计划]
    BookPlan --> CreateBook[生成抄表册本]
    CreateBook --> AssignReader[分配抄表员]
    
    AssignReader --> ReadingStart[开始抄表]
    ReadingStart --> ReadingType{抄表方式}
    
    ReadingType -->|人工抄表| ManualReading[现场抄表录入]
    ReadingType -->|远程抄表| RemoteReading[远程采集数据]
    ReadingType -->|客户自报| SelfReporting[客户自主上报]
    
    ManualReading --> DataValidation[数据校验]
    RemoteReading --> DataValidation
    SelfReporting --> DataValidation
    
    DataValidation --> ValidationResult{校验结果}
    ValidationResult -->|异常| ExceptionHandle[异常处理]
    ValidationResult -->|正常| DataReview[数据复核]
    
    ExceptionHandle --> ReviewException[人工审核异常]
    ReviewException --> DataReview
    
    DataReview --> ReviewResult{复核结果}
    ReviewResult -->|退回| ReadingStart
    ReviewResult -->|通过| BillGeneration[生成账单]
    
    BillGeneration --> CalcWaterFee[计算水费]
    CalcWaterFee --> CalcSewageFee[计算污水费]
    CalcSewageFee --> CalcOtherFee[计算其他费用]
    CalcOtherFee --> BillReview[账单审核]
    
    BillReview --> BillResult{审核结果}
    BillResult -->|退回| BillGeneration
    BillResult -->|通过| BillConfirm[账单确认]
    
    BillConfirm --> SendNotification[发送缴费通知]
    SendNotification --> End([完成开账])

2.2.2 主要功能

册本管理:册本基本信息的维护和管理

  • 册本创建与配置
  • 抄表路线规划
  • 抄表员分配
  • 抄表周期设置

抄表录入:支持多种抄表方式

  • 手工抄表:现场抄表、批量录入
  • 智能抄表:远程数据采集、自动同步
  • 自报抄表:客户自主上报、在线提交

抄表数据审核:确保数据质量

  • 数据校验:读数合理性检查、用量异常检测
  • 异常处理:异常数据标记、人工处理
  • 开账处理:数据确认、账单生成

追加抄表:支持非周期性特殊抄表

  • 补抄管理:漏抄数据补录
  • 特殊抄表:临时抄表需求
  • 调整抄表:读数错误修正

2.2.3 RuoYi-Vue-Pro代码实现

抄表记录Controller层

@RestController
@RequestMapping("/admin-api/water/reading")
@Tag(name = "管理后台 - 抄表管理")
@Validated
public class MeterReadingController {
    
    @Resource
    private MeterReadingService readingService;
    
    @PostMapping("/create")
    @Operation(summary = "创建抄表记录")
    @PreAuthorize("@ss.hasPermission('water:reading:create')")
    public CommonResult<Long> createReading(@Valid @RequestBody MeterReadingSaveReqVO createReqVO) {
        return success(readingService.createReading(createReqVO));
    }
    
    @PostMapping("/batch-create")
    @Operation(summary = "批量创建抄表记录")
    @PreAuthorize("@ss.hasPermission('water:reading:create')")
    public CommonResult<MeterReadingBatchRespVO> batchCreateReading(
            @Valid @RequestBody MeterReadingBatchReqVO batchReqVO) {
        return success(readingService.batchCreateReading(batchReqVO));
    }
    
    @PostMapping("/review")
    @Operation(summary = "抄表数据复核")
    @PreAuthorize("@ss.hasPermission('water:reading:review')")
    public CommonResult<Boolean> reviewReading(@Valid @RequestBody MeterReadingReviewReqVO reviewReqVO) {
        readingService.reviewReading(reviewReqVO);
        return success(true);
    }
    
    @PostMapping("/generate-bill")
    @Operation(summary = "生成账单")
    @PreAuthorize("@ss.hasPermission('water:reading:bill')")
    public CommonResult<BillGenerateRespVO> generateBill(@Valid @RequestBody ReadingBillReqVO reqVO) {
        return success(readingService.generateBill(reqVO));
    }
}

抄表业务Service层

@Service
@Validated
@Slf4j
public class MeterReadingServiceImpl implements MeterReadingService {
    
    @Resource
    private MeterReadingMapper readingMapper;
    @Resource
    private MeterService meterService;
    @Resource
    private BillService billService;
    @Resource
    private WaterPriceService priceService;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createReading(MeterReadingSaveReqVO createReqVO) {
        // 1. 校验水表存在性
        MeterDO meter = meterService.validateMeterExists(createReqVO.getMeterId());
        
        // 2. 校验读数合理性
        validateReadingValue(createReqVO);
        
        // 3. 创建抄表记录
        MeterReadingDO reading = BeanUtils.toBean(createReqVO, MeterReadingDO.class);
        reading.setReadingCode(generateReadingCode());
        reading.setCustomerId(meter.getCustomerId());
        
        // 4. 计算用水量
        BigDecimal waterUsage = calculateWaterUsage(meter.getCurrentReading(), 
                                                   createReqVO.getReadingValue());
        reading.setWaterUsage(waterUsage);
        reading.setReadingStatus(READING_STATUS_PENDING);
        
        readingMapper.insert(reading);
        
        // 5. 更新水表当前读数
        meterService.updateCurrentReading(createReqVO.getMeterId(), 
                                        createReqVO.getReadingValue());
        
        // 6. 记录操作日志
        logReadingOperation(reading.getId(), "创建抄表记录", createReqVO.toString());
        
        return reading.getId();
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MeterReadingBatchRespVO batchCreateReading(MeterReadingBatchReqVO batchReqVO) {
        MeterReadingBatchRespVO result = new MeterReadingBatchRespVO();
        List<MeterReadingDetailVO> successList = new ArrayList<>();
        List<MeterReadingDetailVO> failureList = new ArrayList<>();
        
        for (MeterReadingSaveReqVO item : batchReqVO.getReadingList()) {
            try {
                Long readingId = createReading(item);
                successList.add(buildSuccessDetail(readingId, item));
            } catch (Exception e) {
                log.error("批量抄表失败水表ID{}", item.getMeterId(), e);
                failureList.add(buildFailureDetail(item, e.getMessage()));
            }
        }
        
        result.setSuccessCount(successList.size());
        result.setFailureCount(failureList.size());
        result.setSuccessList(successList);
        result.setFailureList(failureList);
        
        return result;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reviewReading(MeterReadingReviewReqVO reviewReqVO) {
        // 1. 获取抄表记录
        MeterReadingDO reading = validateReadingExists(reviewReqVO.getReadingId());
        
        // 2. 校验状态
        if (!READING_STATUS_PENDING.equals(reading.getReadingStatus())) {
            throw exception(READING_STATUS_INVALID);
        }
        
        // 3. 处理复核结果
        if (reviewReqVO.getReviewResult()) {
            // 复核通过
            reading.setReadingStatus(READING_STATUS_REVIEWED);
            reading.setReviewRemark(reviewReqVO.getReviewRemark());
        } else {
            // 复核退回
            reading.setReadingStatus(READING_STATUS_REJECTED);
            reading.setReviewRemark(reviewReqVO.getReviewRemark());
        }
        
        reading.setReviewerId(reviewReqVO.getReviewerId());
        reading.setReviewTime(LocalDateTime.now());
        
        readingMapper.updateById(reading);
        
        // 4. 记录操作日志
        logReadingOperation(reading.getId(), "数据复核", 
                          "复核结果:" + reviewReqVO.getReviewResult() + ",备注:" + reviewReqVO.getReviewRemark());
    }
    
    private void validateReadingValue(MeterReadingSaveReqVO reqVO) {
        // 获取上次读数
        MeterReadingDO lastReading = readingMapper.selectLastReadingByMeterId(reqVO.getMeterId());
        
        if (lastReading != null) {
            BigDecimal lastValue = lastReading.getReadingValue();
            BigDecimal currentValue = reqVO.getReadingValue();
            
            // 检查读数倒退
            if (currentValue.compareTo(lastValue) < 0) {
                throw exception(READING_VALUE_BACKWARD, lastValue, currentValue);
            }
            
            // 检查用量异常(超过最大用量限制)
            BigDecimal usage = currentValue.subtract(lastValue);
            if (usage.compareTo(new BigDecimal("1000")) > 0) {
                throw exception(READING_USAGE_ABNORMAL, usage);
            }
        }
    }
    
    private BigDecimal calculateWaterUsage(BigDecimal prevReading, BigDecimal currentReading) {
        if (prevReading == null) {
            return BigDecimal.ZERO;
        }
        
        BigDecimal usage = currentReading.subtract(prevReading);
        return usage.max(BigDecimal.ZERO); // 确保用量不为负数
    }
}

Entity实体层

@TableName("water_meter_reading")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MeterReadingDO extends BaseDO {
    
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;
    
    @Schema(description = "抄表记录编号", requiredMode = Schema.RequiredMode.REQUIRED)
    private String readingCode;
    
    @Schema(description = "抄表日期", requiredMode = Schema.RequiredMode.REQUIRED)
    private LocalDate readingDate;
    
    @Schema(description = "抄表时间")
    private LocalDateTime readingTime;
    
    @Schema(description = "抄表读数", requiredMode = Schema.RequiredMode.REQUIRED)
    private BigDecimal readingValue;
    
    @Schema(description = "上次读数")
    private BigDecimal prevReadingValue;
    
    @Schema(description = "用水量", requiredMode = Schema.RequiredMode.REQUIRED)
    private BigDecimal waterUsage;
    
    @Schema(description = "抄表类型", requiredMode = Schema.RequiredMode.REQUIRED)
    private String readingType;
    
    @Schema(description = "抄表方式")
    private String readingMethod;
    
    @Schema(description = "抄表员ID")
    private String readerId;
    
    @Schema(description = "抄表员姓名")
    private String readerName;
    
    @Schema(description = "抄表照片URL")
    private String photoUrl;
    
    @Schema(description = "抄表位置")
    private String readingLocation;
    
    @Schema(description = "异常标识")
    private Boolean abnormalFlag;
    
    @Schema(description = "异常原因")
    private String abnormalReason;
    
    @Schema(description = "备注")
    private String remark;
    
    @Schema(description = "抄表状态", requiredMode = Schema.RequiredMode.REQUIRED)
    private Integer readingStatus;
    
    @Schema(description = "复核人ID")
    private String reviewerId;
    
    @Schema(description = "复核时间")
    private LocalDateTime reviewTime;
    
    @Schema(description = "复核备注")
    private String reviewRemark;
    
    @Schema(description = "水表ID", requiredMode = Schema.RequiredMode.REQUIRED)
    private Long meterId;
    
    @Schema(description = "客户ID", requiredMode = Schema.RequiredMode.REQUIRED)
    private Long customerId;
}

2.3 收费管理

收费管理模块负责水费的收取和管理,是营收系统的重要业务模块。

2.3.1 业务流程图

flowchart TD
    Start([客户缴费]) --> QueryCustomer[查询客户信息]
    QueryCustomer --> CustomerExists{客户是否存在}
    CustomerExists -->|否| ErrorReturn[返回错误信息]
    CustomerExists -->|是| QueryBills[查询欠费账单]
    
    QueryBills --> BillExists{是否有欠费}
    BillExists -->|否| NoDebt[无欠费提示]
    BillExists -->|是| ShowBills[显示账单列表]
    
    ShowBills --> SelectBills[选择缴费账单]
    SelectBills --> CalcAmount[计算缴费金额]
    CalcAmount --> SelectPayMethod[选择支付方式]
    
    SelectPayMethod --> PaymentType{支付方式}
    PaymentType -->|现金| CashPayment[现金收费]
    PaymentType -->|银行卡| BankCardPay[银行卡支付]
    PaymentType -->|在线支付| OnlinePayment[在线支付]
    PaymentType -->|预存款| PrepaidPayment[预存款支付]
    
    CashPayment --> ValidatePayment[验证收费金额]
    BankCardPay --> ValidatePayment
    OnlinePayment --> ThirdPartyPay[第三方支付]
    PrepaidPayment --> CheckBalance[检查预存余额]
    
    ThirdPartyPay --> PaymentCallback[支付回调]
    PaymentCallback --> ValidatePayment
    
    CheckBalance --> BalanceOK{余额是否充足}
    BalanceOK -->|否| InsufficientBalance[余额不足]
    BalanceOK -->|是| ValidatePayment
    
    ValidatePayment --> PaymentSuccess{支付成功}
    PaymentSuccess -->|否| PaymentFailed[支付失败处理]
    PaymentSuccess -->|是| UpdateAccount[更新账户状态]
    
    UpdateAccount --> UpdateBills[更新账单状态]
    UpdateBills --> GenerateReceipt[生成收费凭证]
    GenerateReceipt --> PrintReceipt[打印收据]
    PrintReceipt --> SendNotification[发送缴费通知]
    SendNotification --> Complete([完成缴费])
    
    PaymentFailed --> End([结束])
    InsufficientBalance --> End
    ErrorReturn --> End
    NoDebt --> End

2.3.2 主要功能

柜台收费:现场收费服务

  • 用户查询:客户信息查询、账单查询
  • 收费处理:多种支付方式、找零计算
  • 收费打印:收据打印、发票开具
  • 预存预付:余额充值、预付费管理

柜台结账:营业网点日常结账

  • 日结处理:当日收费汇总、统计分析
  • 交款管理:现金上缴、账务核对
  • 结账查询:历史结账记录查询

预付款管理:预付费业务处理

  • 预付款充值:余额充值、充值记录
  • 使用管理:自动扣款、余额提醒
  • 退款处理:预付款退款、退款审核

缴费记录查询:缴费历史管理

  • 多条件查询:按时间、金额、渠道查询
  • 统计分析:缴费趋势、渠道分析
  • 导出功能:缴费记录导出

2.3.3 RuoYi-Vue-Pro代码实现

缴费Controller层

@RestController
@RequestMapping("/admin-api/water/payment")
@Tag(name = "管理后台 - 缴费管理")
@Validated
public class PaymentController {
    
    @Resource
    private PaymentService paymentService;
    
    @PostMapping("/create")
    @Operation(summary = "创建缴费记录")
    @PreAuthorize("@ss.hasPermission('water:payment:create')")
    public CommonResult<PaymentRespVO> createPayment(@Valid @RequestBody PaymentCreateReqVO createReqVO) {
        return success(paymentService.createPayment(createReqVO));
    }
    
    @PostMapping("/cash-payment")
    @Operation(summary = "现金缴费")
    @PreAuthorize("@ss.hasPermission('water:payment:cash')")
    public CommonResult<PaymentRespVO> cashPayment(@Valid @RequestBody CashPaymentReqVO cashReqVO) {
        return success(paymentService.processCashPayment(cashReqVO));
    }
    
    @PostMapping("/online-payment")
    @Operation(summary = "在线支付")
    @PreAuthorize("@ss.hasPermission('water:payment:online')")
    public CommonResult<OnlinePaymentRespVO> onlinePayment(@Valid @RequestBody OnlinePaymentReqVO onlineReqVO) {
        return success(paymentService.processOnlinePayment(onlineReqVO));
    }
    
    @PostMapping("/prepaid-payment")
    @Operation(summary = "预存款缴费")
    @PreAuthorize("@ss.hasPermission('water:payment:prepaid')")
    public CommonResult<PaymentRespVO> prepaidPayment(@Valid @RequestBody PrepaidPaymentReqVO prepaidReqVO) {
        return success(paymentService.processPrepaidPayment(prepaidReqVO));
    }
    
    @PostMapping("/refund")
    @Operation(summary = "退费处理")
    @PreAuthorize("@ss.hasPermission('water:payment:refund')")
    public CommonResult<Boolean> refundPayment(@Valid @RequestBody PaymentRefundReqVO refundReqVO) {
        paymentService.refundPayment(refundReqVO);
        return success(true);
    }
}

缴费Service层

@Service
@Validated
@Slf4j
public class PaymentServiceImpl implements PaymentService {
    
    @Resource
    private PaymentMapper paymentMapper;
    @Resource
    private BillService billService;
    @Resource
    private CustomerAccountService accountService;
    @Resource
    private PaymentChannelService channelService;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentRespVO createPayment(PaymentCreateReqVO createReqVO) {
        // 1. 校验账单信息
        List<BillDO> bills = validateBills(createReqVO.getBillIds());
        
        // 2. 计算缴费金额
        BigDecimal totalAmount = bills.stream()
                .map(BillDO::getBalanceAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        if (totalAmount.compareTo(createReqVO.getPaymentAmount()) != 0) {
            throw exception(PAYMENT_AMOUNT_MISMATCH);
        }
        
        // 3. 创建缴费记录
        PaymentDO payment = BeanUtils.toBean(createReqVO, PaymentDO.class);
        payment.setPaymentCode(generatePaymentCode());
        payment.setPaymentStatus(PAYMENT_STATUS_PENDING);
        payment.setTotalAmount(totalAmount);
        
        paymentMapper.insert(payment);
        
        // 4. 创建缴费明细
        createPaymentDetails(payment.getId(), bills);
        
        return BeanUtils.toBean(payment, PaymentRespVO.class);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentRespVO processCashPayment(CashPaymentReqVO cashReqVO) {
        // 1. 创建基础缴费记录
        PaymentCreateReqVO createReqVO = BeanUtils.toBean(cashReqVO, PaymentCreateReqVO.class);
        createReqVO.setPaymentChannel("CASH");
        createReqVO.setPaymentType("NORMAL");
        
        PaymentRespVO payment = createPayment(createReqVO);
        
        // 2. 处理现金缴费
        PaymentDO paymentDO = paymentMapper.selectById(payment.getId());
        paymentDO.setActualAmount(cashReqVO.getActualAmount());
        paymentDO.setChangeAmount(cashReqVO.getChangeAmount());
        paymentDO.setOperatorId(cashReqVO.getOperatorId());
        paymentDO.setOutletCode(cashReqVO.getOutletCode());
        paymentDO.setPaymentStatus(PAYMENT_STATUS_SUCCESS);
        paymentDO.setPaymentTime(LocalDateTime.now());
        
        paymentMapper.updateById(paymentDO);
        
        // 3. 更新账单状态
        updateBillStatus(cashReqVO.getBillIds(), payment.getId());
        
        // 4. 更新客户账户
        updateCustomerAccount(cashReqVO.getCustomerId(), cashReqVO.getPaymentAmount());
        
        // 5. 生成收据号
        paymentDO.setInvoiceNo(generateInvoiceNo());
        paymentMapper.updateById(paymentDO);
        
        // 6. 记录操作日志
        logPaymentOperation(payment.getId(), "现金缴费", cashReqVO.toString());
        
        return BeanUtils.toBean(paymentDO, PaymentRespVO.class);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OnlinePaymentRespVO processOnlinePayment(OnlinePaymentReqVO onlineReqVO) {
        // 1. 创建基础缴费记录
        PaymentCreateReqVO createReqVO = BeanUtils.toBean(onlineReqVO, PaymentCreateReqVO.class);
        createReqVO.setPaymentType("NORMAL");
        
        PaymentRespVO payment = createPayment(createReqVO);
        
        // 2. 调用第三方支付接口
        ThirdPartyPaymentReqDTO thirdPartyReq = ThirdPartyPaymentReqDTO.builder()
                .paymentCode(payment.getPaymentCode())
                .paymentChannel(onlineReqVO.getPaymentChannel())
                .totalAmount(onlineReqVO.getPaymentAmount())
                .subject("水费缴费")
                .body("账单缴费-客户:" + onlineReqVO.getCustomerId())
                .notifyUrl(onlineReqVO.getNotifyUrl())
                .returnUrl(onlineReqVO.getReturnUrl())
                .build();
        
        ThirdPartyPaymentRespDTO thirdPartyResp = channelService.createPayment(thirdPartyReq);
        
        // 3. 更新缴费记录
        PaymentDO paymentDO = paymentMapper.selectById(payment.getId());
        paymentDO.setThirdPartyNo(thirdPartyResp.getOutTradeNo());
        paymentDO.setPaymentStatus(PAYMENT_STATUS_PROCESSING);
        paymentMapper.updateById(paymentDO);
        
        // 4. 构建返回结果
        return OnlinePaymentRespVO.builder()
                .paymentId(payment.getId())
                .paymentCode(payment.getPaymentCode())
                .prepayId(thirdPartyResp.getPrepayId())
                .payUrl(thirdPartyResp.getPayUrl())
                .qrCode(thirdPartyResp.getQrCode())
                .build();
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentRespVO processPrepaidPayment(PrepaidPaymentReqVO prepaidReqVO) {
        // 1. 检查预存余额
        CustomerAccountDO account = accountService.getByCustomerId(prepaidReqVO.getCustomerId());
        if (account.getBalance().compareTo(prepaidReqVO.getPaymentAmount()) < 0) {
            throw exception(ACCOUNT_BALANCE_INSUFFICIENT);
        }
        
        // 2. 创建基础缴费记录
        PaymentCreateReqVO createReqVO = BeanUtils.toBean(prepaidReqVO, PaymentCreateReqVO.class);
        createReqVO.setPaymentChannel("PREPAID");
        createReqVO.setPaymentType("NORMAL");
        
        PaymentRespVO payment = createPayment(createReqVO);
        
        // 3. 扣除预存余额
        accountService.deductBalance(prepaidReqVO.getCustomerId(), prepaidReqVO.getPaymentAmount(), 
                                   "水费缴费", payment.getPaymentCode());
        
        // 4. 更新缴费状态
        PaymentDO paymentDO = paymentMapper.selectById(payment.getId());
        paymentDO.setPaymentStatus(PAYMENT_STATUS_SUCCESS);
        paymentDO.setPaymentTime(LocalDateTime.now());
        paymentMapper.updateById(paymentDO);
        
        // 5. 更新账单状态
        updateBillStatus(prepaidReqVO.getBillIds(), payment.getId());
        
        return BeanUtils.toBean(paymentDO, PaymentRespVO.class);
    }
    
    private void updateBillStatus(List<Long> billIds, Long paymentId) {
        for (Long billId : billIds) {
            BillDO bill = billService.getBill(billId);
            bill.setBillStatus(BILL_STATUS_PAID);
            bill.setPaidAmount(bill.getTotalAmount());
            bill.setBalanceAmount(BigDecimal.ZERO);
            bill.setPaymentId(paymentId);
            billService.updateBill(bill);
        }
    }
    
    private void updateCustomerAccount(Long customerId, BigDecimal paymentAmount) {
        CustomerAccountDO account = accountService.getByCustomerId(customerId);
        account.setLastPaymentDate(LocalDate.now());
        account.setLastPaymentAmount(paymentAmount);
        
        // 如果有欠费,减少欠费金额
        if (account.getArrearsAmount().compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal newArrears = account.getArrearsAmount().subtract(paymentAmount);
            account.setArrearsAmount(newArrears.max(BigDecimal.ZERO));
        }
        
        accountService.updateAccount(account);
    }
}

2.4 账务处理

账务处理模块负责处理各类特殊账务情况,主要功能包括:

  • 未销调整:水量调整、金额调整、违约金减免等
  • 特殊开账:特殊情况下的账单生成
  • 账务退款:多缴费退款、预付款退款等
  • 销账调正:对已缴费账单进行调整处理
  • 预存调整:预存余额调整、预存转账等
  • 账务处理日志:记录所有账务处理操作

2.5 发票管理

发票管理模块负责水费发票的管理,主要功能包括:

  • 库存管理:发票入库、领用、作废
  • 发票打印:普通发票和电子发票
  • 发票查询:发票信息查询和统计
  • 发票调整:发票重开、补开

2.6 代收业务

代收业务模块负责处理各种渠道的水费代收业务,主要功能包括:

  • 实时收费:银行代收、支付宝/微信收费、代收点收费
  • 银行代扣:代扣协议管理、代扣数据生成和处理
  • 银行托收:托收单生成、托收数据处理
  • 代扣渠道管理:渠道维护、规则设置、效率分析

2.7 环卫系统

环卫系统模块负责管理与环卫相关的收费和计费业务,主要功能包括:

  • 计费核定:环卫收费规则配置和业务字典维护
  • 计费退补:退费和补缴规则配置,字典配置参与计算
  • 计费减免:环卫费用减免规则配置和审批流程
  • 环卫收费统计:环卫收费数据统计和分析

2.8 业务工单

业务工单模块负责管理日常业务工单的流转和处理,主要功能包括:

  • 业务清单:查询通过系统办理的日常业务工单及进度信息
  • 上报清单:新增、查询问题清单,包括通过手机端上报的问题
  • 稽查工单:对手机端的稽查信息进行多条件查询和导出
  • 移表工单:客户对需要进行移动的水表进行登记
  • 换表工单:新增客户自报的换表和故障的水表等进行换表登记
  • 工作流可视化:工作节点可视化展示和流程管理

3. 表务系统

表务系统负责水表的全生命周期管理,包括水表购置、安装、维修、更换等业务。

3.1 表务工单

表务工单模块负责处理各类表务作业,主要功能包括:

  • 换表工单:换表计划、换表施工、换表回填
  • 移表工单:移表申请、移表施工、移表验收
  • 拆表工单:拆表申请、拆表施工、拆表确认
  • 复装工单:复装申请、复装施工、复装验收
  • 校表工单:校表申请、校表实施、校表结果
  • 稽查工单:水量异常稽查、违规用水稽查、处罚决定
  • 业务上报:异常上报、投诉上报、处理结果反馈

3.2 表务仓库

表务仓库模块负责水表的仓储管理,主要功能包括:

  • 新表入库:水表检定、入库登记、入库确认
  • 水表检定:检定信息记录、结果管理
  • 水表领用:领用单登记、领用单管理
  • 水表出库:出库登记、出库确认
  • 水表退库:退库申请、退库确认
  • 水表报废:报废申请、报废确认
  • 水表生命周期查询:状态查询、历史记录查询

3.3 水表参数与基础信息

水表参数与基础信息模块负责维护水表相关的基础数据,主要功能包括:

  • 水表厂家管理:厂家信息维护、厂家状态管理
  • 水表型号管理:型号信息维护、型号分类管理
  • 水表口径管理:口径信息维护、定换周期设置
  • 水表量程管理:量程信息维护、量程范围设置

3.4 物联网对接与数据同步

物联网对接与数据同步模块负责水表数据的互联互通,主要功能包括:

  • 厂家设备信息管理:设备型号管理、厂家信息维护
  • 表务对接日志:数据同步日志、错误处理
  • 水表数据推送接口:新表数据推送、校验机制
  • 远程抄表数据同步:数据接收、验证与处理
  • 物联网水表监控:状态监控、异常事件报警

4. 报装系统

报装系统负责新用户的报装立户管理,主要功能包括:

4.1 报装流程

报装流程模块负责新用户报装业务的全流程管理,主要功能包括:

  • 报装申请:用户申请、材料审核、现场勘查
  • 方案设计:设计方案、设计审核、费用估算
  • 合同签订:费用通知、合同签订、收费管理
  • 施工管理:施工计划、施工实施、施工验收
  • 开户通水:水表安装、用户立户、通水确认

4.2 一户一表管理

一户一表管理模块负责实施"一户一表"改造,主要功能包括:

  • 改造计划:制定改造计划、用户协商、费用估算
  • 改造实施:施工管理、水表安装、验收管理
  • 用户转换:数据转换、账务处理、使用确认

5. 客户服务

客户服务模块提供多渠道的客户服务功能,主要包括:

5.1 微信、支付宝服务窗

  • 账户绑定:支持用户绑定水务账户
  • 用水查询:查询用水情况和用水趋势
  • 水费查询:查询水费信息和欠费信息
  • 在线缴费:支持在线缴纳水费
  • 业务办理:支持在线办理简单业务

5.2 历史账单

  • 账单查询:查询历史账单信息
  • 用水分析:分析用水趋势,提供图表展示
  • 账单推送:定期推送账单信息
  • 账单明细:提供详细的账单明细

5.3 电子发票

  • 发票申请:申请开具电子发票
  • 发票查询:查询已开具发票
  • 发票下载:下载电子发票
  • 发票推送:推送电子发票到用户邮箱或微信

5.4 营业网点

  • 网点查询:查询营业网点信息
  • 网点导航:提供到营业网点的导航
  • 业务指南:提供各网点业务办理指南
  • 等候情况:实时显示各网点的等候情况

5.5 账户流水

  • 流水查询:查询账户交易流水
  • 明细下载:下载流水明细
  • 交易统计:提供交易金额统计
  • 缴费证明:生成缴费证明

5.6 微网厅

  • 用户注册:用户注册微网厅账号
  • 信息查询:查询用水、缴费信息
  • 业务办理:在线办理各类业务
  • 用户反馈:提交意见建议

6. 系统配置

系统配置模块提供各类系统参数的配置管理功能,主要包括:

6.1 水表参数

  • 水表厂家:管理水表生产厂商信息
  • 水表型号:管理水表型号规格
  • 水表量程:管理水表量程规格

6.2 地址参数

  • 行政区划:管理行政区划信息
  • 地址编码:管理地址编码规则
  • 地址库:维护标准地址库

6.3 价格体系

  • 用水性质:管理不同用水性质的分类
  • 水价标准:管理不同用水性质的水价标准
  • 阶梯水价:管理阶梯水价设置
  • 调价管理:管理水价调整流程

6.4 基本配置

  • 系统参数:管理系统基本参数
  • 业务规则:管理业务处理规则
  • 打印模板:管理各类打印模板
  • 短信模板:管理短信发送模板

6.5 催缴管理

  • 催缴计划:制定欠费催缴计划
  • 催缴任务:分配催缴任务
  • 催缴执行:记录催缴执行情况
  • 催缴结果:统计催缴结果

6.6 用户权限

  • 菜单权限:不同角色可访问的菜单权限配置
  • 功能权限:不同角色可操作的功能权限配置
  • 数据权限:通过查询字典权限控制不同用户业务取数权限
  • 角色管理:自定义角色及权限组合

6.7 定时任务

  • 任务配置:定时任务可视化配置,包含传参设置
  • 任务监控:定时任务执行状态监控
  • 任务日志:定时任务执行日志记录和查询
  • 任务调度:任务优先级和执行顺序管理

7. 系统接口

系统接口模块提供与外部系统的集成和数据交换功能,实现业务数据的互通互联。

7.1 银行接口

银行接口实现与银行系统的对接,支持代扣、托收等功能,主要包括:

  • 收费接口:实现用户通过银行渠道缴纳水费
  • 冲正接口:处理银行退款和交易取消
  • 对账接口:与银行系统进行对账
  • 托收接口:支持银行托收功能
  • 代扣接口:支持银行代扣功能

7.2 支付宝/微信接口

支付宝和微信接口实现与第三方支付平台的对接,支持在线支付功能,主要包括:

  • 欠费查询:查询用户欠费信息
  • 在线支付:支持用户在线缴纳水费
  • 支付通知:处理支付结果通知
  • 对账接口:与支付平台进行对账

7.3 短信接口

短信接口提供短信通知和验证功能,主要包括:

  • 账单通知:通过短信通知用户账单信息
  • 缴费提醒:提醒用户及时缴费
  • 催缴通知:向欠费用户发送催缴短信
  • 业务通知:通知用户业务办理状态
  • 验证码功能:提供短信验证码服务

7.4 集抄系统接口

集抄系统接口实现与智能水表集中抄表系统的对接,主要包括:

  • 抄表数据获取:获取智能水表的抄表数据
  • 水表状态监控:监控水表的使用状态
  • 异常数据处理:处理抄表异常情况

7.5 政务系统接口

政务系统接口实现与地方政务平台和政务APP的对接主要包括

  • 数据推送:推送营收数据到政务平台
  • 数据查询:支持政务平台查询水务数据
  • 缴费对接:支持通过政务平台缴费
  • 报装工单对接:对接报装业务工单

7.6 消火栓系统接口

消火栓系统接口实现与消火栓系统的对接,主要功能包括:

  • 预存缴费管理:管理用户预存水费
  • 剩余水量计算:计算用户剩余可用水量
  • 取水控制:根据预存和剩余水量控制取水

7.7 其他系统对接

其他系统对接模块负责与周边系统进行数据交换和业务协同,主要功能包括:

  • 环卫系统对接:实现与环卫系统的数据同步和业务流程对接
  • 客服系统对接:实现与客服系统的工单同步和问题处理
  • 工单系统对接:实现与工单系统的工单流转和状态同步
  • OA系统对接实现与OA系统的审批流程对接和数据共享
  • 智水擎平台对接:实现与智水擎平台的数据交换和业务协同

8. 统计分析

统计分析模块提供多维度的数据统计和分析功能,为管理决策提供数据支持。

8.1 报表查询

  • 标准报表:系统内置的标准统计报表
  • 自定义报表:用户可自定义的报表
  • 报表导出支持将报表导出为Excel、PDF等格式
  • 报表打印:支持报表打印功能

8.2 欠费查询

  • 欠费情况统计:按区域、用户类型等维度统计欠费情况
  • 欠费用户明细:查询欠费用户的详细信息
  • 欠费分析:分析欠费原因和趋势
  • 欠费导出:支持将欠费数据导出

8.3 缴费记录

  • 缴费情况统计:按多维度统计缴费情况
  • 缴费明细查询:查询缴费明细记录
  • 缴费趋势分析:分析缴费趋势
  • 缴费渠道分析:分析各缴费渠道的使用情况

8.4 用水分析

  • 用水量统计:按多维度统计用水量
  • 用水趋势分析:分析用水趋势,预测用水需求
  • 异常用水分析:识别和分析异常用水情况
  • 节水潜力分析:分析用户节水潜力

9. 工程管理

工程管理模块负责处理与供水工程相关的业务,包括工程申请、施工管理和工程验收等。

9.1 工程申请

  • 工程立项:新建供水工程的立项申请
  • 材料提交:上传工程相关材料
  • 前期勘察:记录工程前期勘察结果
  • 工程预算:制定工程预算方案
  • 申请审批:对工程申请进行审批

9.2 工程施工

  • 施工计划:制定工程施工计划
  • 施工派工:将施工任务分配给施工人员
  • 施工记录:记录施工过程和施工情况
  • 材料管理:管理工程施工材料的使用情况
  • 施工异常处理:处理施工过程中的异常情况

9.3 工程验收

  • 验收申请:提交工程验收申请
  • 验收检查:对工程进行验收检查
  • 验收记录:记录验收结果
  • 竣工结算:进行工程竣工结算
  • 工程归档:对工程资料进行归档

9.4 工程查询

  • 工程进度查询:查询工程进度情况
  • 工程资料查询:查询工程相关资料
  • 工程统计:统计工程数量、金额等信息
  • 工程分析:分析工程实施情况

10. 抄表APP

抄表APP是针对移动端开发的抄表工具支持外勤人员进行现场抄表、问题处理和工单管理等业务操作。

10.1 首页功能

  • 首页:显示当前登录用户信息、快捷搜索和主要和抄表业务相关的功能模块
  • 个人信息:查看个人信息,可以进行密码、手机号信息修改,可以进行抄表设置
  • 快捷查询:提供搜索栏,用户输入户号、户名、地址以及册本后,系统会自动检索到相关的信息

10.2 抄表功能

  • 抄表任务:显示当前登录的抄表员抄表任务信息
  • NFC抄表抄表设备感应NFC后自动弹出抄表页
  • 扫码抄表:扫水表上二维码,搜集该表信息,弹出抄表页
  • 数据采集:抄表数据现场采集功能
  • AI录入对接AI接口实现智能读数
  • 抄表轨迹:记录表的物理位置,在地图上点击后采集水表定位
  • 抄表导航:指引抄表员前往下一个抄表点
  • 抄表汇总:系统会根据当前登录的人员自动汇总抄表信息
  • 账单查询:查询客户账单详情
  • 欠费查询:显示当前登录的抄表员抄表用水客户的欠费情况

10.3 工单管理

  • 问题上报:系统支持上报当前登录的抄表员抄表时遇到的用水问题
  • 问题回填:问题上报后,可进行问题回填和处理
  • 代办工单:显示当前登录的抄表员需要代办工单
  • 平台工单管理:移动端提交工单后,系统会自动提交到工单处置平台进行受理、派发
  • 停水复水工单:当客户存在欠费的情况下可以对该客户进行停水操作
  • 稽查工单:实现抄表稽查和水价稽查
  • 维修工单:提交坏表维修报修等工单

11. 接口服务

接口服务模块提供系统对外的API接口管理和服务能力实现与第三方系统的便捷集成。

11.1 API市场

  • API展示展示系统提供的各类API接口
  • API使用说明提供API接口的详细使用说明和示例
  • API测试提供API接口的在线测试功能

11.2 API管理

  • API申请第三方系统申请调用API的流程管理
  • API调度看板监控API调用情况和性能指标
  • 接口服务配置管理管理API接口的配置参数
  • 接口限流熔断管理控制API接口的调用频率和熔断机制

11.3 接口权限管理

  • 授权管理管理API接口的授权信息
  • 白名单管理设置允许访问API的IP白名单
  • 安全策略设置API调用的安全策略和防护措施

11.4 系统对外接口

  • 查询接口:提供各类数据查询接口
  • 业务处理接口:提供业务处理和操作接口
  • 状态同步接口:提供状态信息同步接口
  • 数据推送接口:提供数据推送和订阅接口