261 lines
12 KiB
Python
261 lines
12 KiB
Python
from rest_framework import serializers
|
|
from django.contrib.auth import get_user_model
|
|
from ..models import (
|
|
QualityIndicator, QualityMeasurement, IncidentReport,
|
|
RiskAssessment, AuditPlan, AuditFinding, ImprovementProject
|
|
)
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class QualityIndicatorSerializer(serializers.ModelSerializer):
|
|
"""Serializer for quality indicators"""
|
|
responsible_department_name = serializers.CharField(source='responsible_department.name', read_only=True)
|
|
responsible_user_name = serializers.CharField(source='responsible_user.get_full_name', read_only=True)
|
|
current_status = serializers.CharField(read_only=True)
|
|
latest_measurement = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = QualityIndicator
|
|
fields = [
|
|
'id', 'name', 'description', 'category', 'type', 'measurement_unit',
|
|
'target_value', 'threshold_warning', 'threshold_critical',
|
|
'calculation_method', 'data_source', 'frequency',
|
|
'responsible_department', 'responsible_department_name',
|
|
'responsible_user', 'responsible_user_name',
|
|
'is_active', 'regulatory_requirement', 'current_status',
|
|
'latest_measurement', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['created_at', 'updated_at', 'current_status']
|
|
|
|
def get_latest_measurement(self, obj):
|
|
"""Get the latest measurement for this indicator"""
|
|
latest = obj.latest_measurement
|
|
if latest:
|
|
return {
|
|
'id': latest.id,
|
|
'measurement_date': latest.measurement_date,
|
|
'value': latest.value,
|
|
'status': latest.status
|
|
}
|
|
return None
|
|
|
|
|
|
class QualityMeasurementSerializer(serializers.ModelSerializer):
|
|
"""Serializer for quality measurements"""
|
|
indicator_name = serializers.CharField(source='indicator.name', read_only=True)
|
|
verified_by_name = serializers.CharField(source='verified_by.get_full_name', read_only=True)
|
|
created_by_name = serializers.CharField(source='created_by.get_full_name', read_only=True)
|
|
|
|
class Meta:
|
|
model = QualityMeasurement
|
|
fields = [
|
|
'id', 'indicator', 'indicator_name', 'measurement_date', 'value',
|
|
'numerator', 'denominator', 'status', 'notes', 'data_source_reference',
|
|
'verified_by', 'verified_by_name', 'verified_at',
|
|
'created_by', 'created_by_name', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['created_by', 'created_at', 'updated_at']
|
|
|
|
def create(self, validated_data):
|
|
"""Set the created_by field to the current user"""
|
|
validated_data['created_by'] = self.context['request'].user
|
|
validated_data['tenant'] = self.context['request'].user.tenant
|
|
return super().create(validated_data)
|
|
|
|
|
|
class IncidentReportSerializer(serializers.ModelSerializer):
|
|
"""Serializer for incident reports"""
|
|
patient_name = serializers.CharField(source='patient.full_name', read_only=True)
|
|
reported_by_name = serializers.CharField(source='reported_by.get_full_name', read_only=True)
|
|
assigned_to_name = serializers.CharField(source='assigned_to.get_full_name', read_only=True)
|
|
|
|
class Meta:
|
|
model = IncidentReport
|
|
fields = [
|
|
'id', 'incident_number', 'title', 'description', 'incident_type',
|
|
'severity', 'category', 'location', 'incident_date', 'discovered_date',
|
|
'patient', 'patient_name', 'reported_by', 'reported_by_name',
|
|
'status', 'priority', 'root_cause', 'contributing_factors',
|
|
'corrective_actions', 'preventive_actions',
|
|
'assigned_to', 'assigned_to_name', 'due_date', 'closed_date',
|
|
'is_confidential', 'regulatory_notification',
|
|
'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['incident_number', 'reported_by', 'created_at', 'updated_at']
|
|
|
|
def create(self, validated_data):
|
|
"""Set the reported_by field to the current user"""
|
|
validated_data['reported_by'] = self.context['request'].user
|
|
validated_data['tenant'] = self.context['request'].user.tenant
|
|
return super().create(validated_data)
|
|
|
|
|
|
class RiskAssessmentSerializer(serializers.ModelSerializer):
|
|
"""Serializer for risk assessments"""
|
|
responsible_person_name = serializers.CharField(source='responsible_person.get_full_name', read_only=True)
|
|
created_by_name = serializers.CharField(source='created_by.get_full_name', read_only=True)
|
|
incident_report_number = serializers.CharField(source='incident_report.incident_number', read_only=True)
|
|
|
|
class Meta:
|
|
model = RiskAssessment
|
|
fields = [
|
|
'id', 'title', 'description', 'risk_category', 'risk_type',
|
|
'likelihood', 'impact', 'risk_score', 'risk_level',
|
|
'current_controls', 'control_effectiveness',
|
|
'residual_likelihood', 'residual_impact', 'residual_risk_score', 'residual_risk_level',
|
|
'mitigation_plan', 'responsible_person', 'responsible_person_name',
|
|
'review_date', 'status', 'incident_report', 'incident_report_number',
|
|
'created_by', 'created_by_name', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = [
|
|
'risk_score', 'risk_level', 'residual_risk_score', 'residual_risk_level',
|
|
'created_by', 'created_at', 'updated_at'
|
|
]
|
|
|
|
def create(self, validated_data):
|
|
"""Set the created_by field to the current user"""
|
|
validated_data['created_by'] = self.context['request'].user
|
|
validated_data['tenant'] = self.context['request'].user.tenant
|
|
return super().create(validated_data)
|
|
|
|
|
|
class AuditFindingSerializer(serializers.ModelSerializer):
|
|
"""Serializer for audit findings"""
|
|
audit_plan_title = serializers.CharField(source='audit_plan.title', read_only=True)
|
|
responsible_person_name = serializers.CharField(source='responsible_person.get_full_name', read_only=True)
|
|
verified_by_name = serializers.CharField(source='verified_by.get_full_name', read_only=True)
|
|
created_by_name = serializers.CharField(source='created_by.get_full_name', read_only=True)
|
|
|
|
class Meta:
|
|
model = AuditFinding
|
|
fields = [
|
|
'id', 'audit_plan', 'audit_plan_title', 'finding_number', 'title', 'description',
|
|
'finding_type', 'severity', 'category', 'criteria_reference', 'evidence',
|
|
'root_cause', 'corrective_action_required', 'corrective_action_plan',
|
|
'responsible_person', 'responsible_person_name',
|
|
'target_completion_date', 'actual_completion_date', 'status',
|
|
'verification_method', 'verified_by', 'verified_by_name', 'verified_date',
|
|
'created_by', 'created_by_name', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['finding_number', 'created_by', 'created_at', 'updated_at']
|
|
|
|
def create(self, validated_data):
|
|
"""Set the created_by field to the current user"""
|
|
validated_data['created_by'] = self.context['request'].user
|
|
validated_data['tenant'] = self.context['request'].user.tenant
|
|
return super().create(validated_data)
|
|
|
|
|
|
class AuditPlanSerializer(serializers.ModelSerializer):
|
|
"""Serializer for audit plans"""
|
|
department_name = serializers.CharField(source='department.name', read_only=True)
|
|
auditor_name = serializers.CharField(source='auditor.get_full_name', read_only=True)
|
|
audit_team_names = serializers.SerializerMethodField()
|
|
created_by_name = serializers.CharField(source='created_by.get_full_name', read_only=True)
|
|
findings_count = serializers.IntegerField(read_only=True)
|
|
open_findings_count = serializers.IntegerField(read_only=True)
|
|
findings = AuditFindingSerializer(many=True, read_only=True)
|
|
|
|
class Meta:
|
|
model = AuditPlan
|
|
fields = [
|
|
'id', 'title', 'description', 'audit_type', 'scope', 'criteria',
|
|
'department', 'department_name', 'auditor', 'auditor_name',
|
|
'audit_team', 'audit_team_names',
|
|
'planned_start_date', 'planned_end_date', 'actual_start_date', 'actual_end_date',
|
|
'status', 'priority', 'regulatory_requirement', 'accreditation_body',
|
|
'findings_count', 'open_findings_count', 'findings',
|
|
'created_by', 'created_by_name', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['findings_count', 'open_findings_count', 'created_by', 'created_at', 'updated_at']
|
|
|
|
def get_audit_team_names(self, obj):
|
|
"""Get names of audit team members"""
|
|
return [member.get_full_name() or member.username for member in obj.audit_team.all()]
|
|
|
|
def create(self, validated_data):
|
|
"""Set the created_by field to the current user"""
|
|
audit_team = validated_data.pop('audit_team', [])
|
|
validated_data['created_by'] = self.context['request'].user
|
|
validated_data['tenant'] = self.context['request'].user.tenant
|
|
|
|
audit_plan = super().create(validated_data)
|
|
audit_plan.audit_team.set(audit_team)
|
|
return audit_plan
|
|
|
|
|
|
class ImprovementProjectSerializer(serializers.ModelSerializer):
|
|
"""Serializer for improvement projects"""
|
|
project_manager_name = serializers.CharField(source='project_manager.get_full_name', read_only=True)
|
|
sponsor_name = serializers.CharField(source='sponsor.get_full_name', read_only=True)
|
|
department_name = serializers.CharField(source='department.name', read_only=True)
|
|
project_team_names = serializers.SerializerMethodField()
|
|
created_by_name = serializers.CharField(source='created_by.get_full_name', read_only=True)
|
|
duration_planned = serializers.IntegerField(read_only=True)
|
|
duration_actual = serializers.IntegerField(read_only=True)
|
|
|
|
class Meta:
|
|
model = ImprovementProject
|
|
fields = [
|
|
'id', 'project_number', 'title', 'description', 'project_type', 'methodology',
|
|
'problem_statement', 'goal_statement', 'success_metrics',
|
|
'baseline_data', 'target_metrics', 'scope',
|
|
'project_manager', 'project_manager_name',
|
|
'project_team', 'project_team_names',
|
|
'sponsor', 'sponsor_name', 'department', 'department_name',
|
|
'planned_start_date', 'planned_end_date', 'actual_start_date', 'actual_end_date',
|
|
'status', 'phase', 'budget', 'actual_cost', 'roi_expected', 'roi_actual',
|
|
'lessons_learned', 'sustainability_plan', 'duration_planned', 'duration_actual',
|
|
'created_by', 'created_by_name', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = [
|
|
'project_number', 'duration_planned', 'duration_actual',
|
|
'created_by', 'created_at', 'updated_at'
|
|
]
|
|
|
|
def get_project_team_names(self, obj):
|
|
"""Get names of project team members"""
|
|
return [member.get_full_name() or member.username for member in obj.project_team.all()]
|
|
|
|
def create(self, validated_data):
|
|
"""Set the created_by field to the current user"""
|
|
project_team = validated_data.pop('project_team', [])
|
|
validated_data['created_by'] = self.context['request'].user
|
|
validated_data['tenant'] = self.context['request'].user.tenant
|
|
|
|
project = super().create(validated_data)
|
|
project.project_team.set(project_team)
|
|
return project
|
|
|
|
|
|
# Summary serializers for dashboard and reporting
|
|
|
|
class QualityMetricsSummarySerializer(serializers.Serializer):
|
|
"""Serializer for quality metrics summary"""
|
|
indicators_count = serializers.IntegerField()
|
|
critical_count = serializers.IntegerField()
|
|
warning_count = serializers.IntegerField()
|
|
open_incidents_count = serializers.IntegerField()
|
|
recent_incidents_count = serializers.IntegerField()
|
|
high_risks_count = serializers.IntegerField()
|
|
active_audits_count = serializers.IntegerField()
|
|
upcoming_audits_count = serializers.IntegerField()
|
|
active_projects_count = serializers.IntegerField()
|
|
|
|
|
|
class IncidentTrendSerializer(serializers.Serializer):
|
|
"""Serializer for incident trend data"""
|
|
date = serializers.DateField()
|
|
count = serializers.IntegerField()
|
|
severity_breakdown = serializers.DictField()
|
|
|
|
|
|
class RiskMatrixSerializer(serializers.Serializer):
|
|
"""Serializer for risk matrix data"""
|
|
likelihood = serializers.CharField()
|
|
impact = serializers.CharField()
|
|
risk_count = serializers.IntegerField()
|
|
risks = RiskAssessmentSerializer(many=True)
|
|
|