Compare commits
No commits in common. "43ef57f1b655e92f78652db441be53ca3307f37b" and "f219effc33154334e95663eee73ff1b9e0b4fa7c" have entirely different histories.
43ef57f1b6
...
f219effc33
4
.gitignore
vendored
4
.gitignore
vendored
@ -97,6 +97,4 @@ database_export/
|
||||
# Lock files
|
||||
*.tar.gz
|
||||
dump.rdb
|
||||
.~lock.*
|
||||
|
||||
node_modules
|
||||
.~lock.*
|
||||
@ -1,95 +0,0 @@
|
||||
# Move Inquiry AI Analysis to Celery Task
|
||||
|
||||
## Summary
|
||||
Replace synchronous AI calls in 3 inquiry creation views with the existing `analyze_inquiry_with_ai.delay()` Celery task.
|
||||
|
||||
## Changes
|
||||
|
||||
### 1. `apps/complaints/ui_views.py` — `inquiry_create` (lines 1554-1567)
|
||||
|
||||
**Replace:**
|
||||
```python
|
||||
from apps.complaints.tasks import _apply_inquiry_ai_analysis
|
||||
from apps.core.ai_service import AIService
|
||||
|
||||
try:
|
||||
analysis = AIService.analyze_inquiry(
|
||||
subject=inquiry.subject,
|
||||
message=inquiry.message,
|
||||
category=inquiry.get_category_display(),
|
||||
hospital_id=inquiry.hospital.id,
|
||||
)
|
||||
emotion_analysis = AIService.analyze_emotion(text=inquiry.message)
|
||||
_apply_inquiry_ai_analysis(inquiry, analysis, emotion_analysis)
|
||||
except Exception as e:
|
||||
logger.error(f"AI analysis failed on inquiry creation: {e}")
|
||||
```
|
||||
|
||||
**With:**
|
||||
```python
|
||||
from apps.complaints.tasks import analyze_inquiry_with_ai
|
||||
|
||||
analyze_inquiry_with_ai.delay(str(inquiry.id))
|
||||
```
|
||||
|
||||
Also update line 1572 — change `"Inquiry created with AI analysis."` to `"Inquiry created."`
|
||||
|
||||
---
|
||||
|
||||
### 2. `apps/complaints/ui_views.py` — `public_inquiry_submit` (lines 2315-2328)
|
||||
|
||||
**Replace:**
|
||||
```python
|
||||
from apps.complaints.tasks import _apply_inquiry_ai_analysis
|
||||
from apps.core.ai_service import AIService
|
||||
|
||||
try:
|
||||
analysis = AIService.analyze_inquiry(
|
||||
subject=inquiry.subject,
|
||||
message=inquiry.message,
|
||||
category=category,
|
||||
hospital_id=hospital.id,
|
||||
)
|
||||
emotion_analysis = AIService.analyze_emotion(text=inquiry.message)
|
||||
_apply_inquiry_ai_analysis(inquiry, analysis, emotion_analysis)
|
||||
except Exception as e:
|
||||
logger.error(f"AI analysis failed on public inquiry creation: {e}")
|
||||
```
|
||||
|
||||
**With:**
|
||||
```python
|
||||
from apps.complaints.tasks import analyze_inquiry_with_ai
|
||||
|
||||
analyze_inquiry_with_ai.delay(str(inquiry.id))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. `apps/complaints/views.py` — `InquiryViewSet.perform_create` (lines 2750-2763)
|
||||
|
||||
**Replace:**
|
||||
```python
|
||||
from apps.complaints.tasks import _apply_inquiry_ai_analysis
|
||||
from apps.core.ai_service import AIService
|
||||
|
||||
try:
|
||||
analysis = AIService.analyze_inquiry(
|
||||
subject=inquiry.subject,
|
||||
message=inquiry.message,
|
||||
category=inquiry.get_category_display(),
|
||||
hospital_id=inquiry.hospital.id,
|
||||
)
|
||||
emotion_analysis = AIService.analyze_emotion(text=inquiry.message)
|
||||
_apply_inquiry_ai_analysis(inquiry, analysis, emotion_analysis)
|
||||
except Exception as e:
|
||||
logger.error(f"AI analysis failed on inquiry creation: {e}")
|
||||
```
|
||||
|
||||
**With:**
|
||||
```python
|
||||
from apps.complaints.tasks import analyze_inquiry_with_ai
|
||||
|
||||
analyze_inquiry_with_ai.delay(str(inquiry.id))
|
||||
```
|
||||
|
||||
Also update docstring on line 2747 from `"Auto-set created_by from request.user and run AI analysis synchronously"` to `"Auto-set created_by from request.user and trigger AI analysis in background"`.
|
||||
@ -1551,14 +1551,25 @@ def inquiry_create(request):
|
||||
|
||||
inquiry.save()
|
||||
|
||||
from apps.complaints.tasks import analyze_inquiry_with_ai
|
||||
from apps.complaints.tasks import _apply_inquiry_ai_analysis
|
||||
from apps.core.ai_service import AIService
|
||||
|
||||
analyze_inquiry_with_ai.delay(str(inquiry.id))
|
||||
try:
|
||||
analysis = AIService.analyze_inquiry(
|
||||
subject=inquiry.subject,
|
||||
message=inquiry.message,
|
||||
category=inquiry.get_category_display(),
|
||||
hospital_id=inquiry.hospital.id,
|
||||
)
|
||||
emotion_analysis = AIService.analyze_emotion(text=inquiry.message)
|
||||
_apply_inquiry_ai_analysis(inquiry, analysis, emotion_analysis)
|
||||
except Exception as e:
|
||||
logger.error(f"AI analysis failed on inquiry creation: {e}")
|
||||
|
||||
InquiryUpdate.objects.create(
|
||||
inquiry=inquiry,
|
||||
update_type="note",
|
||||
message="Inquiry created.",
|
||||
message="Inquiry created with AI analysis.",
|
||||
created_by=request.user,
|
||||
)
|
||||
|
||||
@ -2301,9 +2312,20 @@ def public_inquiry_submit(request):
|
||||
reference_number=reference_number,
|
||||
)
|
||||
|
||||
from apps.complaints.tasks import analyze_inquiry_with_ai
|
||||
from apps.complaints.tasks import _apply_inquiry_ai_analysis
|
||||
from apps.core.ai_service import AIService
|
||||
|
||||
analyze_inquiry_with_ai.delay(str(inquiry.id))
|
||||
try:
|
||||
analysis = AIService.analyze_inquiry(
|
||||
subject=inquiry.subject,
|
||||
message=inquiry.message,
|
||||
category=category,
|
||||
hospital_id=hospital.id,
|
||||
)
|
||||
emotion_analysis = AIService.analyze_emotion(text=inquiry.message)
|
||||
_apply_inquiry_ai_analysis(inquiry, analysis, emotion_analysis)
|
||||
except Exception as e:
|
||||
logger.error(f"AI analysis failed on public inquiry creation: {e}")
|
||||
|
||||
AuditService.log_event(
|
||||
event_type="inquiry_created_public",
|
||||
|
||||
@ -2744,12 +2744,23 @@ class InquiryViewSet(viewsets.ModelViewSet):
|
||||
ordering = ["-created_at"]
|
||||
|
||||
def perform_create(self, serializer):
|
||||
"""Auto-set created_by from request.user and trigger AI analysis in background"""
|
||||
"""Auto-set created_by from request.user and run AI analysis synchronously"""
|
||||
inquiry = serializer.save(created_by=self.request.user)
|
||||
|
||||
from apps.complaints.tasks import analyze_inquiry_with_ai
|
||||
from apps.complaints.tasks import _apply_inquiry_ai_analysis
|
||||
from apps.core.ai_service import AIService
|
||||
|
||||
analyze_inquiry_with_ai.delay(str(inquiry.id))
|
||||
try:
|
||||
analysis = AIService.analyze_inquiry(
|
||||
subject=inquiry.subject,
|
||||
message=inquiry.message,
|
||||
category=inquiry.get_category_display(),
|
||||
hospital_id=inquiry.hospital.id,
|
||||
)
|
||||
emotion_analysis = AIService.analyze_emotion(text=inquiry.message)
|
||||
_apply_inquiry_ai_analysis(inquiry, analysis, emotion_analysis)
|
||||
except Exception as e:
|
||||
logger.error(f"AI analysis failed on inquiry creation: {e}")
|
||||
|
||||
AuditService.log_from_request(
|
||||
event_type="inquiry_created",
|
||||
|
||||
@ -13,8 +13,6 @@ from celery import shared_task
|
||||
from django.utils import timezone
|
||||
from django.core.files.base import ContentFile
|
||||
from celery import shared_task
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -222,7 +222,7 @@ def observation_create(request):
|
||||
title=form.cleaned_data.get("title", ""),
|
||||
location_text=form.cleaned_data.get("location_text", ""),
|
||||
incident_datetime=form.cleaned_data.get("incident_datetime"),
|
||||
reporter_staff_id=user.employee_id or "",
|
||||
reporter_staff_id=user.staff_id or "",
|
||||
reporter_name=user.get_full_name(),
|
||||
reporter_phone="",
|
||||
reporter_email=user.email,
|
||||
|
||||
37
node_modules/.package-lock.json
generated
vendored
37
node_modules/.package-lock.json
generated
vendored
@ -30,15 +30,6 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@fontsource/inter": {
|
||||
"version": "5.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-5.2.8.tgz",
|
||||
"integrity": "sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg==",
|
||||
"license": "OFL-1.1",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ayuhito"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||
@ -229,12 +220,6 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/apexcharts": {
|
||||
"version": "5.10.6",
|
||||
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-5.10.6.tgz",
|
||||
"integrity": "sha512-FJQGbso3iRuOwUYnj0yUhkWeKeJE6aboVol+ae09lsc+lbLMWZqSRbrAWVa/qishLiaeG2icxdvmVkm+9n6kOQ==",
|
||||
"license": "SEE LICENSE IN LICENSE"
|
||||
},
|
||||
"node_modules/arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
@ -469,12 +454,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/htmx.org": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-2.0.8.tgz",
|
||||
"integrity": "sha512-fm297iru0iWsNJlBrjvtN7V9zjaxd+69Oqjh4F/Vq9Wwi2kFisLcrLCiv5oBX0KLfOX/zG8AUo9ROMU5XUB44Q==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
@ -568,12 +547,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lucide": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide/-/lucide-1.8.0.tgz",
|
||||
"integrity": "sha512-JjV/QnadgFLj1Pyu9IKl0lknrolFEzo04B64QcYLLeRzZl/iEHpdbSrRRKbyXcv45SZNv+WGjIUCT33e7xHO6Q==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
@ -1038,16 +1011,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sweetalert2": {
|
||||
"version": "11.26.24",
|
||||
"resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.26.24.tgz",
|
||||
"integrity": "sha512-SLgukW4wicewpW5VOukSXY5Z6DL/z7HCOK2ODSjmQPiSphCN8gJAmh9npoceXOtBRNoDN0xIz+zHYthtfiHmjg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/limonte"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
|
||||
|
||||
44
package-lock.json
generated
44
package-lock.json
generated
@ -7,13 +7,6 @@
|
||||
"": {
|
||||
"name": "hh",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@fontsource/inter": "^5.2.8",
|
||||
"apexcharts": "^5.10.6",
|
||||
"htmx.org": "^2.0.8",
|
||||
"lucide": "^1.8.0",
|
||||
"sweetalert2": "^11.26.24"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@types/node": "^25.5.2",
|
||||
@ -48,15 +41,6 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@fontsource/inter": {
|
||||
"version": "5.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-5.2.8.tgz",
|
||||
"integrity": "sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg==",
|
||||
"license": "OFL-1.1",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ayuhito"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||
@ -247,12 +231,6 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/apexcharts": {
|
||||
"version": "5.10.6",
|
||||
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-5.10.6.tgz",
|
||||
"integrity": "sha512-FJQGbso3iRuOwUYnj0yUhkWeKeJE6aboVol+ae09lsc+lbLMWZqSRbrAWVa/qishLiaeG2icxdvmVkm+9n6kOQ==",
|
||||
"license": "SEE LICENSE IN LICENSE"
|
||||
},
|
||||
"node_modules/arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
@ -502,12 +480,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/htmx.org": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-2.0.8.tgz",
|
||||
"integrity": "sha512-fm297iru0iWsNJlBrjvtN7V9zjaxd+69Oqjh4F/Vq9Wwi2kFisLcrLCiv5oBX0KLfOX/zG8AUo9ROMU5XUB44Q==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
@ -601,12 +573,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lucide": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide/-/lucide-1.8.0.tgz",
|
||||
"integrity": "sha512-JjV/QnadgFLj1Pyu9IKl0lknrolFEzo04B64QcYLLeRzZl/iEHpdbSrRRKbyXcv45SZNv+WGjIUCT33e7xHO6Q==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
@ -1071,16 +1037,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sweetalert2": {
|
||||
"version": "11.26.24",
|
||||
"resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.26.24.tgz",
|
||||
"integrity": "sha512-SLgukW4wicewpW5VOukSXY5Z6DL/z7HCOK2ODSjmQPiSphCN8gJAmh9npoceXOtBRNoDN0xIz+zHYthtfiHmjg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/limonte"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "3.4.19",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
|
||||
|
||||
@ -26,12 +26,5 @@
|
||||
"tailwindcss": "^3.4.19",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^6.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/inter": "^5.2.8",
|
||||
"apexcharts": "^5.10.6",
|
||||
"htmx.org": "^2.0.8",
|
||||
"lucide": "^1.8.0",
|
||||
"sweetalert2": "^11.26.24"
|
||||
}
|
||||
}
|
||||
|
||||
5
static/vendor/apexcharts/apexcharts.min.js
vendored
5
static/vendor/apexcharts/apexcharts.min.js
vendored
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user