[feat] 水表全生命周期管理功能
- 实现水表入库/安装/换表/报废的完整生命周期管理 - 添加详细的操作日志记录,支持操作人、时间戳、照片等 - 实现库存统计功能,按状态、口径、类型、制造商分类统计 - 添加 REST API 接口,支持水表操作和查询 - 创建 DTO 类用于数据传输 - 添加数据库升级脚本,支持新增字段和视图创建 - 插入测试数据验证功能完整性 功能包括: 1. 水表入库操作及日志记录 2. 水表安装操作,继承客户信息 3. 故障换表操作,自动完成新旧表状态转换 4. 水表报废操作,记录报废原因 5. 全生命周期日志查询 6. 库存统计分析 7. 水表详情查询 8. 最近操作记录查询 关闭 Issue #53: [表务] 水表全生命周期管理(入库/安装/换表/报废)
This commit is contained in:
+3
-2
@@ -6,8 +6,9 @@
|
||||
|
||||
<parent>
|
||||
<groupId>com.water</groupId>
|
||||
<artifactId>water-management-system</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<artifactId>wm-parent</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>wm-revenue</artifactId>
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
package com.water.revenue.controller;
|
||||
|
||||
import com.water.revenue.service.MeterService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/api/meter/lifecycle")
|
||||
public class MeterLifecycleController {
|
||||
|
||||
private final MeterService meterService;
|
||||
|
||||
/**
|
||||
* 水表入库
|
||||
*/
|
||||
@PostMapping("/stock-in")
|
||||
public ResponseEntity<?> stockIn(
|
||||
@RequestParam String meterNo,
|
||||
@RequestParam String caliber,
|
||||
@RequestParam String meterType,
|
||||
@RequestParam String manufacturer,
|
||||
@RequestParam int quantity,
|
||||
@RequestParam String operatorId,
|
||||
@RequestParam String operatorName) {
|
||||
|
||||
try {
|
||||
meterService.stockIn(meterNo, caliber, meterType, manufacturer, quantity, operatorId, operatorName);
|
||||
return ResponseEntity.ok().body(Map.of("success", true, "message", "水表入库成功"));
|
||||
} catch (Exception e) {
|
||||
log.error("水表入库失败", e);
|
||||
return ResponseEntity.badRequest().body(Map.of("success", false, "message", "水表入库失败: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 水表安装
|
||||
*/
|
||||
@PostMapping("/install")
|
||||
public ResponseEntity<?> install(
|
||||
@RequestParam Long meterId,
|
||||
@RequestParam Long customerId,
|
||||
@RequestParam String address,
|
||||
@RequestParam BigDecimal initialReading,
|
||||
@RequestParam String operatorId,
|
||||
@RequestParam String operatorName) {
|
||||
|
||||
try {
|
||||
meterService.install(meterId, customerId, address, initialReading, operatorId, operatorName);
|
||||
return ResponseEntity.ok().body(Map.of("success", true, "message", "水表安装成功"));
|
||||
} catch (Exception e) {
|
||||
log.error("水表安装失败", e);
|
||||
return ResponseEntity.badRequest().body(Map.of("success", false, "message", "水表安装失败: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 故障换表
|
||||
*/
|
||||
@PostMapping("/replace")
|
||||
public ResponseEntity<?> replace(
|
||||
@RequestParam Long oldMeterId,
|
||||
@RequestParam Long newMeterId,
|
||||
@RequestParam BigDecimal oldReading,
|
||||
@RequestParam String remark,
|
||||
@RequestParam String operatorId,
|
||||
@RequestParam String operatorName) {
|
||||
|
||||
try {
|
||||
meterService.replace(oldMeterId, newMeterId, oldReading, remark, operatorId, operatorName);
|
||||
return ResponseEntity.ok().body(Map.of("success", true, "message", "换表成功"));
|
||||
} catch (Exception e) {
|
||||
log.error("换表失败", e);
|
||||
return ResponseEntity.badRequest().body(Map.of("success", false, "message", "换表失败: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 水表报废
|
||||
*/
|
||||
@PostMapping("/scrap")
|
||||
public ResponseEntity<?> scrap(
|
||||
@RequestParam Long meterId,
|
||||
@RequestParam String reason,
|
||||
@RequestParam String operatorId,
|
||||
@RequestParam String operatorName) {
|
||||
|
||||
try {
|
||||
meterService.scrap(meterId, reason, operatorId, operatorName);
|
||||
return ResponseEntity.ok().body(Map.of("success", true, "message", "水表报废成功"));
|
||||
} catch (Exception e) {
|
||||
log.error("水表报废失败", e);
|
||||
return ResponseEntity.badRequest().body(Map.of("success", false, "message", "水表报废失败: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询水表生命周期记录
|
||||
*/
|
||||
@GetMapping("/lifecycle/{meterId}")
|
||||
public ResponseEntity<List<Map<String, Object>>> getLifecycle(@PathVariable Long meterId) {
|
||||
List<Map<String, Object>> lifecycle = meterService.getLifecycle(meterId);
|
||||
return ResponseEntity.ok(lifecycle);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取库存统计
|
||||
*/
|
||||
@GetMapping("/inventory/stats")
|
||||
public ResponseEntity<Map<String, Object>> getInventoryStats() {
|
||||
Map<String, Object> stats = meterService.getInventoryStats();
|
||||
return ResponseEntity.ok(stats);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询库存水表
|
||||
*/
|
||||
@GetMapping("/inventory")
|
||||
public ResponseEntity<List<Map<String, Object>>> getWarehouseMeters(
|
||||
@RequestParam(required = false) String caliber,
|
||||
@RequestParam(required = false) String meterType,
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "20") int size) {
|
||||
|
||||
List<Map<String, Object>> meters = meterService.getWarehouseMeters(caliber, meterType, page, size);
|
||||
return ResponseEntity.ok(meters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最近操作记录
|
||||
*/
|
||||
@GetMapping("/recent-operations")
|
||||
public ResponseEntity<List<Map<String, Object>>> getRecentOperations(@RequestParam(defaultValue = "10") int limit) {
|
||||
List<Map<String, Object>> operations = meterService.getRecentOperations(limit);
|
||||
return ResponseEntity.ok(operations);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取水表详情
|
||||
*/
|
||||
@GetMapping("/{meterId}")
|
||||
public ResponseEntity<Map<String, Object>> getMeterDetails(@PathVariable Long meterId) {
|
||||
Map<String, Object> details = meterService.getMeterDetails(meterId);
|
||||
return ResponseEntity.ok(details);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.water.revenue.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MeterInventoryStatsDTO {
|
||||
|
||||
// 总体统计
|
||||
private Long totalWarehouse;
|
||||
private Long totalActive;
|
||||
private Long totalDismantled;
|
||||
private Long totalScrapped;
|
||||
|
||||
// 按状态统计
|
||||
private Map<String, Long> statusStats;
|
||||
|
||||
// 按口径统计
|
||||
private Map<String, Long> caliberStats;
|
||||
|
||||
// 按类型统计
|
||||
private Map<String, Long> typeStats;
|
||||
|
||||
// 按制造商统计
|
||||
private Map<String, Long> manufacturerStats;
|
||||
|
||||
// 最近操作
|
||||
private List<MeterOperationLogDTO> recentOperations;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.water.revenue.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MeterOperationLogDTO {
|
||||
|
||||
private Long id;
|
||||
private Long meterId;
|
||||
private String meterNo;
|
||||
private String operationType;
|
||||
private String operationName;
|
||||
private BigDecimal oldReading;
|
||||
private BigDecimal newReading;
|
||||
private String equipmentNo;
|
||||
private Long operatorId;
|
||||
private String operatorName;
|
||||
private List<String> photos;
|
||||
private String remark;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
// 操作类型中文名称映射
|
||||
public String getOperationName() {
|
||||
switch (operationType) {
|
||||
case "install": return "安装";
|
||||
case "dismantle": return "拆除";
|
||||
case "replace": return "更换";
|
||||
case "scrap": return "报废";
|
||||
case "stock_in": return "入库";
|
||||
case "repair": return "维修";
|
||||
case "calibrate": return "校准";
|
||||
case "refurbish": return "翻新";
|
||||
default: return operationType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,35 +17,42 @@ public class MeterService {
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
/** 水表入库 */
|
||||
public void stockIn(String meterNo, String caliber, String meterType, String manufacturer, int quantity) {
|
||||
@Transactional
|
||||
public void stockIn(String meterNo, String caliber, String meterType, String manufacturer, int quantity, String operatorId, String operatorName) {
|
||||
for (int i = 0; i < quantity; i++) {
|
||||
String no = meterNo + "-" + (i + 1);
|
||||
jdbcTemplate.update(
|
||||
"INSERT INTO rev_meter (meter_no, caliber, meter_type, manufacturer, status) VALUES (?,?,?,?,?)",
|
||||
no, caliber, meterType, manufacturer, "warehouse");
|
||||
|
||||
// 记录入库日志
|
||||
jdbcTemplate.update(
|
||||
"INSERT INTO rev_meter_log (meter_id, operation_type, operator_id, operator_name, remark) VALUES (?,?,?,?,?)",
|
||||
jdbcTemplate.queryForObject("SELECT id FROM rev_meter WHERE meter_no = ?", Long.class, no),
|
||||
"stock_in", operatorId, operatorName, "水表入库:" + meterNo + "-" + (i + 1));
|
||||
}
|
||||
log.info("Meter stock in: {} x{}", meterNo, quantity);
|
||||
}
|
||||
|
||||
/** 水表出库安装 */
|
||||
@Transactional
|
||||
public void install(Long meterId, Long customerId, String address, BigDecimal initialReading) {
|
||||
public void install(Long meterId, Long customerId, String address, BigDecimal initialReading, String operatorId, String operatorName) {
|
||||
jdbcTemplate.update(
|
||||
"UPDATE rev_meter SET customer_id = ?, install_address = ?, initial_reading = ?, current_reading = ?, status = 'active', install_date = CURRENT_DATE WHERE id = ?",
|
||||
customerId, address, initialReading, initialReading, meterId);
|
||||
jdbcTemplate.update(
|
||||
"INSERT INTO rev_meter_log (meter_id, operation_type, old_reading, new_reading, remark) VALUES (?,?,?,?,?)",
|
||||
meterId, "install", BigDecimal.ZERO, initialReading, "新表安装");
|
||||
"INSERT INTO rev_meter_log (meter_id, operation_type, operator_id, operator_name, old_reading, new_reading, remark) VALUES (?,?,?,?,?,?,?)",
|
||||
meterId, "install", operatorId, operatorName, BigDecimal.ZERO, initialReading, "新表安装");
|
||||
}
|
||||
|
||||
/** 故障换表 */
|
||||
@Transactional
|
||||
public void replace(Long oldMeterId, Long newMeterId, BigDecimal oldReading, String remark) {
|
||||
public void replace(Long oldMeterId, Long newMeterId, BigDecimal oldReading, String remark, String operatorId, String operatorName) {
|
||||
// 旧表拆除
|
||||
jdbcTemplate.update("UPDATE rev_meter SET status = 'dismantled', current_reading = ? WHERE id = ?", oldReading, oldMeterId);
|
||||
jdbcTemplate.update("UPDATE rev_meter SET status = 'dismantled', current_reading = ?, dismantle_date = CURRENT_DATE WHERE id = ?", oldReading, oldMeterId);
|
||||
jdbcTemplate.update(
|
||||
"INSERT INTO rev_meter_log (meter_id, operation_type, old_reading, remark) VALUES (?,?,?,?)",
|
||||
oldMeterId, "dismantle", oldReading, remark);
|
||||
"INSERT INTO rev_meter_log (meter_id, operation_type, operator_id, operator_name, old_reading, remark) VALUES (?,?,?,?,?,?)",
|
||||
oldMeterId, "dismantle", operatorId, operatorName, oldReading, remark);
|
||||
|
||||
// 新表安装(继承客户信息)
|
||||
Map<String, Object> oldMeter = jdbcTemplate.queryForMap("SELECT customer_id, install_address FROM rev_meter WHERE id = ?", oldMeterId);
|
||||
@@ -53,16 +60,20 @@ public class MeterService {
|
||||
"UPDATE rev_meter SET customer_id = ?, install_address = ?, status = 'active', install_date = CURRENT_DATE WHERE id = ?",
|
||||
oldMeter.get("customer_id"), oldMeter.get("install_address"), newMeterId);
|
||||
jdbcTemplate.update(
|
||||
"INSERT INTO rev_meter_log (meter_id, operation_type, new_meter_no, remark) VALUES (?,?,?,?)",
|
||||
newMeterId, "change", String.valueOf(newMeterId), "替换旧表 #" + oldMeterId);
|
||||
"INSERT INTO rev_meter_log (meter_id, operation_type, operator_id, operator_name, new_meter_no, remark) VALUES (?,?,?,?,?,?)",
|
||||
newMeterId, "change", operatorId, operatorName, String.valueOf(newMeterId), "替换旧表 #" + oldMeterId);
|
||||
|
||||
log.info("Meter replaced: old={}, new={}, operator={}", oldMeterId, newMeterId, operatorId);
|
||||
}
|
||||
|
||||
/** 水表报废 */
|
||||
public void scrap(Long meterId, String reason) {
|
||||
jdbcTemplate.update("UPDATE rev_meter SET status = 'scrapped' WHERE id = ?", meterId);
|
||||
@Transactional
|
||||
public void scrap(Long meterId, String reason, String operatorId, String operatorName) {
|
||||
jdbcTemplate.update("UPDATE rev_meter SET status = 'scrapped', scrapped_date = CURRENT_DATE WHERE id = ?", meterId);
|
||||
jdbcTemplate.update(
|
||||
"INSERT INTO rev_meter_log (meter_id, operation_type, remark) VALUES (?,?,?)",
|
||||
meterId, "scrap", reason);
|
||||
"INSERT INTO rev_meter_log (meter_id, operation_type, operator_id, operator_name, remark) VALUES (?,?,?,?,?)",
|
||||
meterId, "scrap", operatorId, operatorName, reason);
|
||||
log.info("Meter scrapped: id={}, reason={}", meterId, reason);
|
||||
}
|
||||
|
||||
/** 查询水表生命周期记录 */
|
||||
@@ -71,4 +82,92 @@ public class MeterService {
|
||||
"SELECT * FROM rev_meter_log WHERE meter_id = ? ORDER BY created_at",
|
||||
meterId);
|
||||
}
|
||||
|
||||
/** 库存统计 */
|
||||
public Map<String, Object> getInventoryStats() {
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
|
||||
// 按状态统计
|
||||
List<Map<String, Object>> statusStats = jdbcTemplate.queryForList(
|
||||
"SELECT status, COUNT(*) as count FROM rev_meter GROUP BY status");
|
||||
stats.put("statusStats", statusStats);
|
||||
|
||||
// 按口径统计
|
||||
List<Map<String, Object>> caliberStats = jdbcTemplate.queryForList(
|
||||
"SELECT caliber, COUNT(*) as count FROM rev_meter WHERE status = 'warehouse' GROUP BY caliber");
|
||||
stats.put("caliberStats", caliberStats);
|
||||
|
||||
// 按类型统计
|
||||
List<Map<String, Object>> typeStats = jdbcTemplate.queryForList(
|
||||
"SELECT meter_type, COUNT(*) as count FROM rev_meter WHERE status = 'warehouse' GROUP BY meter_type");
|
||||
stats.put("typeStats", typeStats);
|
||||
|
||||
// 按制造商统计
|
||||
List<Map<String, Object>> manufacturerStats = jdbcTemplate.queryForList(
|
||||
"SELECT manufacturer, COUNT(*) as count FROM rev_meter WHERE status = 'warehouse' GROUP BY manufacturer");
|
||||
stats.put("manufacturerStats", manufacturerStats);
|
||||
|
||||
// 总库存
|
||||
Long totalWarehouse = jdbcTemplate.queryForObject(
|
||||
"SELECT COUNT(*) FROM rev_meter WHERE status = 'warehouse'", Long.class);
|
||||
stats.put("totalWarehouse", totalWarehouse);
|
||||
|
||||
// 活跃水表数
|
||||
Long totalActive = jdbcTemplate.queryForObject(
|
||||
"SELECT COUNT(*) FROM rev_meter WHERE status = 'active'", Long.class);
|
||||
stats.put("totalActive", totalActive);
|
||||
|
||||
// 其他状态计数
|
||||
Long totalDismantled = jdbcTemplate.queryForObject(
|
||||
"SELECT COUNT(*) FROM rev_meter WHERE status = 'dismantled'", Long.class);
|
||||
stats.put("totalDismantled", totalDismantled);
|
||||
|
||||
Long totalScrapped = jdbcTemplate.queryForObject(
|
||||
"SELECT COUNT(*) FROM rev_meter WHERE status = 'scrapped'", Long.class);
|
||||
stats.put("totalScrapped", totalScrapped);
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/** 库存查询 */
|
||||
public List<Map<String, Object>> getWarehouseMeters(String caliber, String meterType, int page, int size) {
|
||||
String sql = "SELECT * FROM rev_meter WHERE status = 'warehouse'";
|
||||
List<Object> params = new ArrayList<>();
|
||||
|
||||
if (caliber != null && !caliber.isEmpty()) {
|
||||
sql += " AND caliber = ?";
|
||||
params.add(caliber);
|
||||
}
|
||||
if (meterType != null && !meterType.isEmpty()) {
|
||||
sql += " AND meter_type = ?";
|
||||
params.add(meterType);
|
||||
}
|
||||
|
||||
sql += " ORDER BY created_at DESC LIMIT ? OFFSET ?";
|
||||
params.add(size);
|
||||
params.add(page * size);
|
||||
|
||||
return jdbcTemplate.queryForList(sql, params.toArray());
|
||||
}
|
||||
|
||||
/** 获取最近操作记录 */
|
||||
public List<Map<String, Object>> getRecentOperations(int limit) {
|
||||
return jdbcTemplate.queryForList(
|
||||
"SELECT rml.*, rm.meter_no " +
|
||||
"FROM rev_meter_log rml " +
|
||||
"JOIN rev_meter rm ON rml.meter_id = rm.id " +
|
||||
"ORDER BY rml.created_at DESC LIMIT ?", limit);
|
||||
}
|
||||
|
||||
/** 获取水表详情 */
|
||||
public Map<String, Object> getMeterDetails(Long meterId) {
|
||||
Map<String, Object> meter = jdbcTemplate.queryForMap(
|
||||
"SELECT * FROM rev_meter WHERE id = ?", meterId);
|
||||
|
||||
// 获取生命周期记录
|
||||
List<Map<String, Object>> lifecycle = getLifecycle(meterId);
|
||||
meter.put("lifecycle", lifecycle);
|
||||
|
||||
return meter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,9 @@ CREATE TABLE IF NOT EXISTS rev_meter (
|
||||
install_date DATE,
|
||||
install_address VARCHAR(300),
|
||||
status VARCHAR(20) DEFAULT 'active', -- active/dismantled/scrapped/repaired/warehouse
|
||||
install_date DATE,
|
||||
scrapped_date DATE,
|
||||
dismantle_date DATE,
|
||||
remark VARCHAR(500),
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
@@ -64,12 +67,14 @@ COMMENT ON TABLE rev_meter IS '水表档案表';
|
||||
CREATE TABLE IF NOT EXISTS rev_meter_log (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
meter_id BIGINT REFERENCES rev_meter(id),
|
||||
operation_type VARCHAR(30) NOT NULL, -- install/dismantle/repair/change/scrap/calibrate/refurbish
|
||||
operation_type VARCHAR(30) NOT NULL, -- install/dismantle/repair/change/scrap/calibrate/refurbish/stock_in
|
||||
old_reading DECIMAL(10,2),
|
||||
new_reading DECIMAL(10,2),
|
||||
new_meter_no VARCHAR(50),
|
||||
operator_id BIGINT,
|
||||
operator_name VARCHAR(50),
|
||||
photos JSONB, -- 现场照片URL数组
|
||||
equipment_no VARCHAR(50), -- 设备编号(如新换的表号)
|
||||
photos JSONB, -- 现场照片URL数组
|
||||
remark VARCHAR(500),
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
-- 水表全生命周期管理升级脚本
|
||||
-- 添加缺失的日期字段到水表表
|
||||
|
||||
-- 为水表表添加安装、拆除、报废日期字段
|
||||
ALTER TABLE rev_meter ADD COLUMN IF NOT EXISTS install_date DATE;
|
||||
ALTER TABLE rev_meter ADD COLUMN IF NOT EXISTS scrapped_date DATE;
|
||||
ALTER TABLE rev_meter ADD COLUMN IF NOT EXISTS dismantle_date DATE;
|
||||
|
||||
-- 添加照片和设备编号字段到日志表
|
||||
ALTER TABLE rev_meter_log ADD COLUMN IF NOT EXISTS photos JSONB;
|
||||
ALTER TABLE rev_meter_log ADD COLUMN IF NOT EXISTS equipment_no VARCHAR(50);
|
||||
|
||||
-- 创建水表统计视图
|
||||
CREATE OR REPLACE VIEW v_meter_statistics AS
|
||||
SELECT
|
||||
status,
|
||||
COUNT(*) as count,
|
||||
COUNT(CASE WHEN install_date IS NOT NULL THEN 1 END) as installed_count,
|
||||
COUNT(CASE WHEN scrapped_date IS NOT NULL THEN 1 END) as scrapped_count,
|
||||
COUNT(CASE WHEN dismantle_date IS NOT NULL THEN 1 END) as dismantled_count
|
||||
FROM rev_meter
|
||||
GROUP BY status;
|
||||
|
||||
-- 创建库存统计视图
|
||||
CREATE OR REPLACE VIEW v_meter_inventory AS
|
||||
SELECT
|
||||
status,
|
||||
caliber,
|
||||
meter_type,
|
||||
manufacturer,
|
||||
COUNT(*) as count
|
||||
FROM rev_meter
|
||||
GROUP BY status, caliber, meter_type, manufacturer
|
||||
ORDER BY status, caliber, meter_type, manufacturer;
|
||||
|
||||
-- 为水表操作类型添加注释
|
||||
COMMENT ON COLUMN rev_meter.status IS 'active/dismantled/scrapped/repaired/warehouse';
|
||||
COMMENT ON COLUMN rev_meter_log.operation_type IS 'install/dismantle/repair/change/scrap/calibrate/refurbish/stock_in';
|
||||
@@ -0,0 +1,40 @@
|
||||
-- 水表全生命周期管理测试数据
|
||||
-- 插入测试用水表数据
|
||||
|
||||
-- 插入测试用水表(仓库状态)
|
||||
INSERT INTO rev_meter (meter_no, caliber, meter_type, manufacturer, status, created_at) VALUES
|
||||
('WH001', 'DN15', 'mechanical', '威胜', 'warehouse', CURRENT_TIMESTAMP),
|
||||
('WH002', 'DN20', 'mechanical', '威胜', 'warehouse', CURRENT_TIMESTAMP),
|
||||
('WH003', 'DN15', 'electromagnetic', '三川', 'warehouse', CURRENT_TIMESTAMP),
|
||||
('WH004', 'DN25', 'ultrasonic', '宁水', 'warehouse', CURRENT_TIMESTAMP),
|
||||
('WH005', 'DN40', 'mechanical', '威胜', 'warehouse', CURRENT_TIMESTAMP),
|
||||
('WH006', 'DN50', 'electromagnetic', '三川', 'warehouse', CURRENT_TIMESTAMP),
|
||||
('WH007', 'DN80', 'ultrasonic', '宁水', 'warehouse', CURRENT_TIMESTAMP),
|
||||
('WH008', 'DN100', 'ultrasonic', '宁水', 'warehouse', CURRENT_TIMESTAMP),
|
||||
('WH009', 'DN15', 'mechanical', '威胜', 'warehouse', CURRENT_TIMESTAMP),
|
||||
('WH010', 'DN20', 'electromagnetic', '三川', 'warehouse', CURRENT_TIMESTAMP)
|
||||
ON CONFLICT (meter_no) DO NOTHING;
|
||||
|
||||
-- 插入一些已安装的水表用于测试
|
||||
INSERT INTO rev_meter (meter_no, customer_id, caliber, meter_type, manufacturer, status, install_date, initial_reading, current_reading, created_at) VALUES
|
||||
('M001', 1, 'DN15', 'mechanical', '威胜', 'active', '2025-01-01', 0.00, 1200.50, CURRENT_TIMESTAMP),
|
||||
('M002', 2, 'DN20', 'electromagnetic', '三川', 'active', '2025-02-01', 0.00, 2100.75, CURRENT_TIMESTAMP),
|
||||
('M003', 3, 'DN15', 'ultrasonic', '宁水', 'dismantled', '2025-03-01', 0.00, 3200.00, CURRENT_TIMESTAMP),
|
||||
('M004', 4, 'DN25', 'mechanical', '威胜', 'scrapped', '2025-04-01', 0.00, 1500.25, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT (meter_no) DO NOTHING;
|
||||
|
||||
-- 插入一些操作记录测试数据
|
||||
INSERT INTO rev_meter_log (meter_id, operation_type, operator_id, operator_name, old_reading, new_reading, remark, created_at) VALUES
|
||||
((SELECT id FROM rev_meter WHERE meter_no = 'M001'), 'install', '1001', '张三', 0.00, 100.00, '新表安装', CURRENT_TIMESTAMP - INTERVAL '1 year'),
|
||||
((SELECT id FROM rev_meter WHERE meter_no = 'M001'), 'calibrate', '1002', '李四', 1100.00, 1100.50, '年度校准', CURRENT_TIMESTAMP - INTERVAL '6 months'),
|
||||
((SELECT id FROM rev_meter WHERE meter_no = 'M001'), 'repair', '1001', '张三', 1150.00, 1150.00, '更换电池', CURRENT_TIMESTAMP - INTERVAL '3 months'),
|
||||
|
||||
((SELECT id FROM rev_meter WHERE meter_no = 'M002'), 'install', '1001', '张三', 0.00, 200.00, '新表安装', CURRENT_TIMESTAMP - INTERVAL '1 year'),
|
||||
((SELECT id FROM rev_meter WHERE meter_no = 'M002'), 'replace', '1003', '王五', 2000.00, 2100.75, '故障换表', CURRENT_TIMESTAMP - INTERVAL '1 month'),
|
||||
|
||||
((SELECT id FROM rev_meter WHERE meter_no = 'M003'), 'install', '1001', '张三', 0.00, 300.00, '新表安装', CURRENT_TIMESTAMP - INTERVAL '2 years'),
|
||||
((SELECT id FROM rev_meter WHERE meter_no = 'M003'), 'dismantle', '1004', '赵六', 3000.00, 3200.00, '客户要求拆除', CURRENT_TIMESTAMP - INTERVAL '1 month'),
|
||||
|
||||
((SELECT id FROM rev_meter WHERE meter_no = 'M004'), 'install', '1001', '张三', 0.00, 400.00, '新表安装', CURRENT_TIMESTAMP - INTERVAL '2 years'),
|
||||
((SELECT id FROM rev_meter WHERE meter_no = 'M004'), 'scrap', '1004', '赵六', 1500.25, NULL, '到期报废', CURRENT_TIMESTAMP - INTERVAL '1 month')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
Reference in New Issue
Block a user