Add CI pipeline for Docker image builds
Some checks failed
Build and Push Docker Image / build (push) Failing after 21s

This commit is contained in:
ismail 2026-04-19 13:34:40 +03:00
parent f219effc33
commit 946c31cf34
273 changed files with 316 additions and 58 deletions

2
.gitignore vendored
View File

@ -98,3 +98,5 @@ database_export/
*.tar.gz
dump.rdb
.~lock.*
node_modules

View File

@ -0,0 +1,95 @@
# 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"`.

View File

@ -1551,25 +1551,14 @@ def inquiry_create(request):
inquiry.save()
from apps.complaints.tasks import _apply_inquiry_ai_analysis
from apps.core.ai_service import AIService
from apps.complaints.tasks import analyze_inquiry_with_ai
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}")
analyze_inquiry_with_ai.delay(str(inquiry.id))
InquiryUpdate.objects.create(
inquiry=inquiry,
update_type="note",
message="Inquiry created with AI analysis.",
message="Inquiry created.",
created_by=request.user,
)
@ -2312,20 +2301,9 @@ def public_inquiry_submit(request):
reference_number=reference_number,
)
from apps.complaints.tasks import _apply_inquiry_ai_analysis
from apps.core.ai_service import AIService
from apps.complaints.tasks import analyze_inquiry_with_ai
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}")
analyze_inquiry_with_ai.delay(str(inquiry.id))
AuditService.log_event(
event_type="inquiry_created_public",

View File

@ -2744,23 +2744,12 @@ class InquiryViewSet(viewsets.ModelViewSet):
ordering = ["-created_at"]
def perform_create(self, serializer):
"""Auto-set created_by from request.user and run AI analysis synchronously"""
"""Auto-set created_by from request.user and trigger AI analysis in background"""
inquiry = serializer.save(created_by=self.request.user)
from apps.complaints.tasks import _apply_inquiry_ai_analysis
from apps.core.ai_service import AIService
from apps.complaints.tasks import analyze_inquiry_with_ai
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}")
analyze_inquiry_with_ai.delay(str(inquiry.id))
AuditService.log_from_request(
event_type="inquiry_created",

View File

@ -13,6 +13,8 @@ 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__)

View File

@ -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.staff_id or "",
reporter_staff_id=user.employee_id or "",
reporter_name=user.get_full_name(),
reporter_phone="",
reporter_email=user.email,

37
node_modules/.package-lock.json generated vendored
View File

@ -30,6 +30,15 @@
"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",
@ -220,6 +229,12 @@
"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",
@ -454,6 +469,12 @@
"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",
@ -547,6 +568,12 @@
"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",
@ -1011,6 +1038,16 @@
"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
View File

@ -7,6 +7,13 @@
"": {
"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",
@ -41,6 +48,15 @@
"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",
@ -231,6 +247,12 @@
"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",
@ -480,6 +502,12 @@
"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",
@ -573,6 +601,12 @@
"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",
@ -1037,6 +1071,16 @@
"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",

View File

@ -26,5 +26,12 @@
"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"
}
}

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