更新福建水务营收系统项目管理文档,调整模块设计文档的状态为修复中,完成度提升至95%,质量评级调整为B+级。修正模块设计文档中的代码示例,替换为核心接口定义和前端界面设计,确保文档内容符合甲方A级交付标准,提升信息的完整性和一致性。
This commit is contained in:
parent
e8413119b0
commit
da49f93abe
@ -18,7 +18,7 @@
|
||||
| 文档名称 | 状态 | 完成度 | 质量评级 | 最后更新 | 备注 |
|
||||
|---------|------|--------|----------|----------|------|
|
||||
| `water_biz_system_architecture.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已全面适配OpenGauss,架构图完整 |
|
||||
| `water_biz_module_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已补充业务流程图和完整代码示例 |
|
||||
| `water_biz_module_design.md` | 🔄 修复中 | 95% | B+级 | 2024-12-19 | 正在修复代码示例重复问题 |
|
||||
| `water_biz_database_design.md` | ✅ 已完成 | 100% | A+级 | 2024-12-19 | 已适配OpenGauss,完整DDL和安全设计 |
|
||||
| `water_biz_interface_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已补充详细接口参数、代码示例和安全设计 |
|
||||
| `water_biz_deployment_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已补充容器化部署方案和自动化脚本 |
|
||||
|
||||
@ -26,13 +26,13 @@
|
||||
- [3.2 抄表开账](#32-抄表开账)
|
||||
- [3.2.1 业务流程图](#321-业务流程图)
|
||||
- [3.2.2 主要功能](#322-主要功能)
|
||||
- [3.2.3 RuoYi-Vue-Pro代码实现](#323-ruoyi-vue-pro代码实现)
|
||||
- [3.2.4 前端Vue3代码实现](#324-前端vue3代码实现)
|
||||
- [3.2.3 核心接口定义](#323-核心接口定义)
|
||||
- [3.2.4 前端界面设计](#324-前端界面设计)
|
||||
- [3.3 收费管理](#33-收费管理)
|
||||
- [3.3.1 业务流程图](#331-业务流程图)
|
||||
- [3.3.2 主要功能](#332-主要功能)
|
||||
- [3.3.3 RuoYi-Vue-Pro代码实现](#333-ruoyi-vue-pro代码实现)
|
||||
- [3.3.4 前端Vue3代码实现](#334-前端vue3代码实现)
|
||||
- [3.3.3 核心接口定义](#333-核心接口定义)
|
||||
- [3.3.4 前端界面设计](#334-前端界面设计)
|
||||
- [3.4 账务处理](#34-账务处理)
|
||||
- [3.5 发票管理](#35-发票管理)
|
||||
- [3.6 代收业务](#36-代收业务)
|
||||
@ -488,527 +488,100 @@ flowchart TD
|
||||
- 特殊抄表:临时抄表需求
|
||||
- 调整抄表:读数错误修正
|
||||
|
||||
#### 3.2.3 RuoYi-Vue-Pro代码实现
|
||||
#### 3.2.3 核心接口定义
|
||||
|
||||
**抄表记录Controller层**:
|
||||
**抄表管理主要接口**:
|
||||
```java
|
||||
@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));
|
||||
}
|
||||
public CommonResult<Long> createReading(@Valid @RequestBody MeterReadingSaveReqVO 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));
|
||||
}
|
||||
public CommonResult<MeterReadingBatchRespVO> batchCreateReading(@Valid @RequestBody MeterReadingBatchReqVO 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);
|
||||
}
|
||||
public CommonResult<Boolean> reviewReading(@Valid @RequestBody MeterReadingReviewReqVO reviewReqVO);
|
||||
|
||||
@PostMapping("/generate-bill")
|
||||
@Operation(summary = "生成账单")
|
||||
@PreAuthorize("@ss.hasPermission('water:reading:bill')")
|
||||
public CommonResult<BillGenerateRespVO> generateBill(@Valid @RequestBody ReadingBillReqVO reqVO) {
|
||||
return success(readingService.generateBill(reqVO));
|
||||
}
|
||||
public CommonResult<BillGenerateRespVO> generateBill(@Valid @RequestBody ReadingBillReqVO reqVO);
|
||||
}
|
||||
```
|
||||
|
||||
**抄表业务Service层**:
|
||||
```java
|
||||
@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); // 确保用量不为负数
|
||||
}
|
||||
}
|
||||
**核心业务逻辑**:
|
||||
- 抄表数据校验:读数合理性检查、用量异常检测
|
||||
- 批量处理机制:支持批量抄表录入和结果反馈
|
||||
- 数据复核流程:多级审核机制确保数据质量
|
||||
- 账单生成:基于抄表数据自动计算费用并生成账单
|
||||
|
||||
#### 3.2.4 前端界面设计
|
||||
|
||||
**抄表管理页面结构**:
|
||||
```vue
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 查询条件 -->
|
||||
<el-form class="search-form" inline>
|
||||
<el-form-item label="抄表日期">
|
||||
<el-date-picker v-model="queryParams.readingDate" type="daterange" />
|
||||
</el-form-item>
|
||||
<el-form-item label="抄表状态">
|
||||
<el-select v-model="queryParams.status">
|
||||
<el-option label="待复核" value="pending" />
|
||||
<el-option label="已通过" value="approved" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
<el-button @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-row class="mb-10px">
|
||||
<el-button type="primary" @click="handleAdd">新增抄表</el-button>
|
||||
<el-button type="success" @click="handleBatchAdd">批量抄表</el-button>
|
||||
<el-button type="warning" @click="handleExport">导出数据</el-button>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table v-loading="loading" :data="readingList">
|
||||
<el-table-column prop="readingCode" label="抄表编号" width="180" />
|
||||
<el-table-column prop="customerName" label="客户名称" />
|
||||
<el-table-column prop="meterCode" label="水表编号" />
|
||||
<el-table-column prop="readingValue" label="本次读数" />
|
||||
<el-table-column prop="waterUsage" label="用水量" />
|
||||
<el-table-column prop="readingDate" label="抄表日期" />
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template #default="{ row }">
|
||||
<dict-tag :type="DICT_TYPE.READING_STATUS" :value="row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link @click="handleUpdate(row)">编辑</el-button>
|
||||
<el-button link @click="handleReview(row)">复核</el-button>
|
||||
<el-button link type="danger" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
```
|
||||
|
||||
**Entity实体层**:
|
||||
```java
|
||||
@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;
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2.4 前端Vue3代码实现
|
||||
|
||||
**抄表记录Controller层**:
|
||||
```java
|
||||
@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层**:
|
||||
```java
|
||||
@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实体层**:
|
||||
```java
|
||||
@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;
|
||||
}
|
||||
```
|
||||
**前端页面功能特性**:
|
||||
- 响应式设计:基于Element Plus的现代化UI组件
|
||||
- 数据表格:支持分页、排序、筛选等功能
|
||||
- 表单验证:前端数据校验和错误提示
|
||||
- 批量操作:支持批量抄表录入和批量审核
|
||||
- 实时更新:页面数据实时刷新和状态同步
|
||||
|
||||
### 3.3 收费管理
|
||||
|
||||
@ -1088,54 +661,30 @@ flowchart TD
|
||||
- 统计分析:缴费趋势、渠道分析
|
||||
- 导出功能:缴费记录导出
|
||||
|
||||
#### 3.3.3 RuoYi-Vue-Pro代码实现
|
||||
#### 3.3.3 核心接口定义
|
||||
|
||||
**缴费Controller层**:
|
||||
**缴费管理主要接口**:
|
||||
```java
|
||||
@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));
|
||||
}
|
||||
public CommonResult<PaymentRespVO> createPayment(@Valid @RequestBody PaymentCreateReqVO 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));
|
||||
}
|
||||
public CommonResult<PaymentRespVO> cashPayment(@Valid @RequestBody CashPaymentReqVO 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));
|
||||
}
|
||||
public CommonResult<OnlinePaymentRespVO> onlinePayment(@Valid @RequestBody OnlinePaymentReqVO 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);
|
||||
}
|
||||
public CommonResult<PaymentRespVO> prepaidPayment(@Valid @RequestBody PrepaidPaymentReqVO prepaidReqVO);
|
||||
}
|
||||
```
|
||||
|
||||
@ -1318,55 +867,49 @@ public class PaymentServiceImpl implements PaymentService {
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.3.4 前端Vue3代码实现
|
||||
#### 3.3.4 前端界面设计
|
||||
|
||||
**缴费Controller层**:
|
||||
```java
|
||||
@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);
|
||||
}
|
||||
}
|
||||
**缴费管理页面结构**:
|
||||
```vue
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 客户查询 -->
|
||||
<el-form class="search-form" inline>
|
||||
<el-form-item label="客户编号">
|
||||
<el-input v-model="queryParams.customerCode" placeholder="请输入客户编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="客户姓名">
|
||||
<el-input v-model="queryParams.customerName" placeholder="请输入客户姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
<el-button @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 账单信息 -->
|
||||
<el-table v-loading="loading" :data="billList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="billCode" label="账单编号" />
|
||||
<el-table-column prop="billDate" label="账期" />
|
||||
<el-table-column prop="waterUsage" label="用水量" />
|
||||
<el-table-column prop="totalAmount" label="应缴金额" />
|
||||
<el-table-column prop="balanceAmount" label="欠费金额" />
|
||||
</el-table>
|
||||
|
||||
<!-- 缴费操作 -->
|
||||
<el-row class="payment-actions">
|
||||
<el-col :span="12">
|
||||
<el-statistic title="选中金额" :value="selectedAmount" prefix="¥" />
|
||||
</el-col>
|
||||
<el-col :span="12" class="text-right">
|
||||
<el-button type="success" @click="handleCashPayment">现金缴费</el-button>
|
||||
<el-button type="primary" @click="handleOnlinePayment">在线支付</el-button>
|
||||
<el-button type="warning" @click="handlePrepaidPayment">预存扣费</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
```
|
||||
|
||||
**缴费Service层**:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user