治理记录与治理报告工作流程优化方案
# 治理记录与治理报告工作流程优化方案
是的,治理记录与治理报告之间同样需要优化以支持"先治理后报告"的工作流程。这种优化完全符合实际安全管理操作,让我们进行系统性的优化:
## 模型关系优化
```python
class HazardRectificationRecord(models.Model):
"""
隐患治理记录模型 (核心治理实体)
"""
rectification_id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False,
verbose_name=_('治理ID')
)
inspection_record = models.OneToOneField(
HazardInspectionRecord,
on_delete=models.CASCADE,
related_name='rectification_record',
verbose_name=_('对应排查记录')
)
rectification_notes = models.TextField(verbose_name=_('整改说明'))
rectified_by = models.ForeignKey(
SecureUser,
on_delete=models.PROTECT,
limit_choices_to={'role': SecureUser.UserRoles.HAZARD_RECTIFIER},
related_name='rectified_hazards',
verbose_name=_('治理员')
)
rectification_date = models.DateTimeField(verbose_name=_('整改时间'))
report = models.ForeignKey( # 新增可选关联
'HazardRectificationReport',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='rectification_records',
verbose_name=_('所属报告')
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('创建时间'))
updated_at = models.DateTimeField(auto_now=True, verbose_name=_('更新时间'))
class HazardRectificationReport(models.Model):
"""
隐患治理报告模型 (汇总多个治理记录)
"""
report_id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False,
verbose_name=_('报告ID')
)
rectification_date = models.DateTimeField(
verbose_name=_('报告提交日期'),
help_text=_('实际治理完成日期可能早于此日期')
)
overall_description = models.TextField(
verbose_name=_('治理情况描述'),
help_text=_('基于多个治理记录的总结性描述')
)
submitted_by = models.ForeignKey(
SecureUser,
on_delete=models.PROTECT,
limit_choices_to={'role': SecureUser.UserRoles.HAZARD_RECTIFIER},
related_name='submitted_rectifications',
verbose_name=_('报告提交人')
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('创建时间'))
updated_at = models.DateTimeField(auto_now=True, verbose_name=_('更新时间'))
```
## 序列化器优化
```python
class HazardRectificationRecordSerializer(serializers.ModelSerializer):
inspection_details = serializers.SerializerMethodField(
label=_('排查详情')
)
class Meta:
model = HazardRectificationRecord
fields = '__all__'
read_only_fields = ['rectification_id', 'created_at', 'inspection_details']
extra_kwargs = {
'rectified_by': {'default': serializers.CurrentUserDefault()},
'report': {'required': False, 'allow_null': True}
}
def get_inspection_details(self, obj):
"""获取关联的排查记录详情"""
record = obj.inspection_record
return {
"description": record.description,
"location": record.location,
"hazard_level": record.get_hazard_level_display()
}
class HazardRectificationReportSerializer(serializers.ModelSerializer):
# 动态获取关联记录
rectification_records = serializers.SerializerMethodField(
label=_('治理记录')
)
submitted_by_name = serializers.CharField(
source='submitted_by.username',
read_only=True,
label=_('提交人姓名')
)
class Meta:
model = HazardRectificationReport
fields = '__all__'
extra_kwargs = {
'submitted_by': {'default': serializers.CurrentUserDefault()}
}
def get_rectification_records(self, obj):
"""获取关联的治理记录"""
records = obj.rectification_records.all()
return HazardRectificationRecordSerializer(records, many=True).data
def create(self, validated_data):
# 支持创建报告时关联现有记录
record_ids = self.context['request'].data.get('record_ids', [])
report = super().create(validated_data)
# 关联记录
if record_ids:
records = HazardRectificationRecord.objects.filter(
rectification_id__in=record_ids,
rectified_by=self.context['request'].user
)
records.update(report=report)
return report
```
## 视图集功能增强
```python
class HazardRectificationRecordViewSet(viewsets.ModelViewSet):
"""隐患治理记录视图集 (优化)"""
queryset = HazardRectificationRecord.objects.all()
serializer_class = HazardRectificationRecordSerializer
permission_classes = [IsAuthenticated, IsHazardRectifier]
@action(detail=False, methods=['get'])
def unassigned(self, request):
"""获取未关联报告的治理记录"""
queryset = self.get_queryset().filter(
report__isnull=True,
rectified_by=request.user
)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
class HazardRectificationReportViewSet(viewsets.ModelViewSet):
"""隐患治理报告视图集 (优化)"""
queryset = HazardRectificationReport.objects.all()
serializer_class = HazardRectificationReportSerializer
permission_classes = [IsAuthenticated, IsHazardRectifier]
@action(detail=True, methods=['post'])
def add_records(self, request, pk=None):
"""向报告添加治理记录"""
report = self.get_object()
record_ids = request.data.get('record_ids', [])
# 验证记录属于当前用户
records = HazardRectificationRecord.objects.filter(
rectification_id__in=record_ids,
rectified_by=request.user
)
# 关联记录
updated = records.update(report=report)
return Response({
"status": f"成功关联{updated}条记录",
"report_id": str(report.report_id)
})
@action(detail=True, methods=['post'])
def generate_report(self, request, pk=None):
"""自动生成治理报告内容"""
report = self.get_object()
records = report.rectification_records.all()
# 自动生成报告描述
if not report.overall_description:
# 统计治理情况
completed = records.filter(completion_status='completed').count()
in_progress = records.filter(completion_status='in_progress').count()
total = records.count()
report.overall_description = (
f"本报告包含{total}项治理任务,其中{completed}项已完全整改完成,"
f"{in_progress}项正在整改中。主要整改内容包括配电安全、消防设施等。"
)
report.save()
return Response(HazardRectificationReportSerializer(report).data)
```
## 完整治理工作流 API 示例
### 1. 创建治理记录(独立)
```http
POST /api/rectification-records/
Content-Type: multipart/form-data
Authorization: Bearer <token>
{
"inspection_record": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"rectification_notes": "已清理安全出口",
"rectification_date": "2023-06-16T10:00:00Z",
"rectification_images": [<image1>, <image2>]
}
```
### 2. 获取未关联的治理记录
```http
GET /api/rectification-records/unassigned/
Authorization: Bearer <token>
```
### 3. 创建治理报告并关联记录
```http
POST /api/rectification-reports/
Content-Type: application/json
Authorization: Bearer <token>
{
"rectification_date": "2023-06-20T14:00:00Z",
"record_ids": [
"d4e5f6a7-b8c9-4d0e-9f10-111213141516",
"e5f6a7b8-c9d0-4e1f-9a11-121314151617"
]
}
```
### 4. 为已有报告添加治理记录
```http
POST /api/rectification-reports/{report_id}/add_records/
Content-Type: application/json
Authorization: Bearer <token>
{
"record_ids": ["f6a7b8c9-d0e1-4f2a-9b12-131415161718"]
}
```
### 5. 自动生成报告内容
```http
POST /api/rectification-reports/{report_id}/generate_report/
Authorization: Bearer <token>
```
## 数据库优化
```sql
-- 治理记录报告关联索引
CREATE INDEX idx_rectification_report ON hazards_hazardrectificationrecord (report_id);
-- 用户治理记录查询优化
CREATE INDEX idx_user_rectifications ON hazards_hazardrectificationrecord (rectified_by, created_at);
-- 未关联记录查询优化
CREATE INDEX idx_unassigned_rectifications ON hazards_hazardrectificationrecord (report_id)
WHERE report_id IS NULL;
```
## 安全增强措施
1. **治理记录所有权验证**:
```python
def get_object(self):
obj = super().get_object()
if obj.rectified_by != self.request.user:
raise PermissionDenied("您无权操作此治理记录")
return obj
```
2. **报告提交人验证**:
```python
def perform_create(self, serializer):
report = serializer.save(submitted_by=self.request.user)
# 验证所有记录属于当前用户
record_ids = self.request.data.get('record_ids', [])
if record_ids:
user_records_count = HazardRectificationRecord.objects.filter(
rectification_id__in=record_ids,
rectified_by=self.request.user
).count()
if user_records_count != len(record_ids):
raise PermissionDenied("部分记录不属于当前用户")
```
3. **审计日志增强**:
```python
@receiver(post_save, sender=HazardRectificationRecord)
def log_rectification_change(sender, instance, created, **kwargs):
action = "创建" if created else "更新"
logger.info(
f"隐患治理记录{action} | 记录ID:{instance.rectification_id} "
f"操作人:{instance.rectified_by} "
f"关联报告:{instance.report.report_id if instance.report else '无'}"
)
```
## 治理工作流程对比
| 阶段 | 优化前工作流 | 优化后工作流 |
|------|--------------|--------------|
| **治理执行** | 必须先有报告才能治理 | 可独立执行治理任务 |
| **报告创建** | 报告创建时需包含所有治理记录 | 可先创建空报告,后添加治理记录 |
| **记录关联** | 固定关联,难以调整 | 灵活关联和解关联 |
| **跨期汇总** | 无法汇总不同时期的治理工作 | 可汇总任意时间段的治理记录 |
| **部分提交** | 必须全部完成才能提交报告 | 可分批提交治理成果 |
## 迁移策略
1. **数据库迁移脚本**:
```python
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('hazards', 'previous_migration'),
]
operations = [
migrations.AddField(
model_name='hazardrectificationrecord',
name='report',
field=models.ForeignKey(
null=True,
blank=True,
on_delete=models.SET_NULL,
to='hazards.HazardRectificationReport',
verbose_name='所属报告'
),
),
migrations.AlterField(
model_name='hazardrectificationreport',
name='related_inspections',
field=models.ManyToManyField(
blank=True,
to='hazards.HazardInspectionReport',
verbose_name='关联排查报告'
),
),
]
```
2. **数据迁移**:
```python
# 将现有记录关联到报告
for report in HazardRectificationReport.objects.all():
# 假设原有关联通过外键间接存在
related_records = HazardRectificationRecord.objects.filter(
inspection_record__report__in=report.related_inspections.all()
)
related_records.update(report=report)
```
## 企业级优势
1. **流程灵活性**:
- 支持现场即时治理记录
- 允许后期汇总和调整
- 适应不同治理周期需求
2. **合规性提升**:
- 完整记录治理过程
- 保留原始治理证据
- 支持追溯审计
3. **操作效率**:
- 减少前期规划负担
- 降低数据录入错误
- 简化报告生成过程
4. **安全控制**:
- 严格的所有权验证
- 操作审计追踪
- 数据完整性保护
这种优化使治理模块完全符合"先执行后报告"的实际工作流程,同时保持了系统的安全性和合规性,特别适合企业级安全隐患治理系统的需求。