99 Commits

Author SHA1 Message Date
github-actions[bot]
f53125cfdc 🔄 Update image to 147 [CI SKIP] 2026-04-30 11:05:42 +00:00
65ab51e652 Merge pull request 'update' (#128) from shaxob into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m11s
Reviewed-on: #128
2026-04-30 11:03:51 +00:00
2997810fae Merge pull request 'behruz' (#129) from behruz into main
Some checks failed
Deploy to Production / build-and-deploy (push) Has been cancelled
Reviewed-on: #129
2026-04-30 11:03:44 +00:00
xoliqberdiyev
d014f5a2fb fix 2026-04-30 16:02:04 +05:00
xoliqberdiyev
7d49929772 Merge branch 'main' of https://gitea.felixits.uz/sifatbaho/backend-v1 into behruz 2026-04-30 15:22:18 +05:00
Shaxobff
c29546a04b update 2026-04-30 11:11:12 +05:00
xoliqberdiyev
b39c080de3 add tasks app 2026-04-29 18:40:51 +05:00
github-actions[bot]
7ad385af94 🔄 Update image to 145 [CI SKIP] 2026-04-29 12:30:39 +00:00
3781ce29e5 Merge pull request 'shaxob' (#127) from shaxob into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m19s
Reviewed-on: #127
2026-04-29 12:28:42 +00:00
Shaxobff
db7e34c1c2 update 2026-04-29 16:12:12 +05:00
Shaxobff
1cb9551e81 update 2026-04-29 14:21:33 +05:00
Shaxobff
51b30c2cc4 update 2026-04-29 11:57:23 +05:00
Shaxobff
dc4c98bfc9 update 2026-04-29 11:18:50 +05:00
github-actions[bot]
abed9e59b4 🔄 Update image to 144 [CI SKIP] 2026-04-28 13:41:10 +00:00
f238c92a09 Merge pull request 'fix' (#125) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m11s
Reviewed-on: #125
2026-04-28 13:32:46 +00:00
xoliqberdiyev
113f2da120 fix 2026-04-28 18:32:24 +05:00
github-actions[bot]
99b265f68f 🔄 Update image to 143 [CI SKIP] 2026-04-28 13:19:46 +00:00
c5d60e799c Merge pull request 'fix' (#124) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m17s
Reviewed-on: #124
2026-04-28 13:17:52 +00:00
xoliqberdiyev
7829c9c625 fix 2026-04-28 18:17:21 +05:00
github-actions[bot]
7f462674a8 🔄 Update image to 142 [CI SKIP] 2026-04-28 13:05:16 +00:00
f7be3be5d2 Merge pull request 'behruz' (#123) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m12s
Reviewed-on: #123
2026-04-28 13:03:29 +00:00
xoliqberdiyev
557f9f821d Merge branch 'main' of https://gitea.felixits.uz/sifatbaho/backend-v1 into behruz 2026-04-28 18:03:07 +05:00
xoliqberdiyev
5f70d69896 fux 2026-04-28 18:02:39 +05:00
github-actions[bot]
4ea7070a8f 🔄 Update image to 141 [CI SKIP] 2026-04-28 12:50:39 +00:00
8b02f3a3a3 Merge pull request 'add new admin user delete api' (#122) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m12s
Reviewed-on: #122
2026-04-28 12:48:46 +00:00
xoliqberdiyev
f0d93b10ac Merge branch 'main' of https://gitea.felixits.uz/sifatbaho/backend-v1 into behruz 2026-04-28 17:48:03 +05:00
xoliqberdiyev
172ddf4da4 add new admin user delete api 2026-04-28 17:47:55 +05:00
435dd56334 Merge pull request 'fix error' (#121) from behruz into main
Some checks failed
Deploy to Production / build-and-deploy (push) Has been cancelled
Reviewed-on: #121
2026-04-28 12:40:16 +00:00
xoliqberdiyev
779c9db924 fix error 2026-04-28 17:39:55 +05:00
eaaba123b0 Merge pull request 'add new fields to request-evalution api' (#120) from behruz into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 53s
Reviewed-on: #120
2026-04-28 12:30:43 +00:00
xoliqberdiyev
63c4ad81eb add new fields to request-evalution api 2026-04-28 17:30:11 +05:00
github-actions[bot]
d065891ad5 🔄 Update image to 138 [CI SKIP] 2026-04-28 11:11:54 +00:00
94c4d03925 Merge pull request 'remove unused fields from auto-evalution model' (#119) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m10s
Reviewed-on: #119
2026-04-28 11:10:06 +00:00
xoliqberdiyev
4a958f064b remove unused fields from auto-evalution model 2026-04-28 16:09:25 +05:00
github-actions[bot]
d1f0a5a9ae 🔄 Update image to 137 [CI SKIP] 2026-04-28 11:07:21 +00:00
0084d11c62 Merge pull request 'change response of permissions apis' (#118) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 4m25s
Reviewed-on: #118
2026-04-28 11:05:35 +00:00
xoliqberdiyev
d1340cdd52 change response of permissions apis 2026-04-28 16:04:59 +05:00
github-actions[bot]
d7ea1acba6 🔄 Update image to 136 [CI SKIP] 2026-04-27 12:57:34 +00:00
560cbe8000 Merge pull request 'fix certificate create api' (#117) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m11s
Reviewed-on: #117
2026-04-27 12:55:46 +00:00
xoliqberdiyev
37d6a93529 fix certificate create api 2026-04-27 17:55:21 +05:00
github-actions[bot]
e1b445d515 🔄 Update image to 135 [CI SKIP] 2026-04-27 12:49:45 +00:00
ef87112c79 Merge pull request 'behruz' (#116) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m8s
Reviewed-on: #116
2026-04-27 12:47:57 +00:00
xoliqberdiyev
8c01c1dc2d Merge branch 'main' of https://gitea.felixits.uz/sifatbaho/backend-v1 into behruz 2026-04-27 17:47:33 +05:00
xoliqberdiyev
921b54ab7c change url 2026-04-27 17:47:20 +05:00
github-actions[bot]
a74c348187 🔄 Update image to 134 [CI SKIP] 2026-04-27 12:44:14 +00:00
52fab30588 Merge pull request 'fix 500 error' (#115) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m8s
Reviewed-on: #115
2026-04-27 12:42:29 +00:00
xoliqberdiyev
0de50ec328 fix 500 error 2026-04-27 17:41:13 +05:00
github-actions[bot]
e346546d24 🔄 Update image to 133 [CI SKIP] 2026-04-27 12:09:19 +00:00
e97c6c7ab2 Merge pull request 'update deploy.yaml file' (#114) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 4m28s
Reviewed-on: #114
2026-04-27 12:07:23 +00:00
github-actions[bot]
f7706e77ee 🔄 Update image to 132 [CI SKIP] 2026-04-27 12:07:15 +00:00
xoliqberdiyev
e351ed5303 update deploy.yaml file 2026-04-27 17:06:43 +05:00
affd3e1221 Merge pull request 'add filter to archive apis' (#113) from behruz into main
Some checks failed
Deploy to Production / build-and-deploy (push) Has been cancelled
Reviewed-on: #113
2026-04-27 12:05:24 +00:00
xoliqberdiyev
59ed3d23ac add filter to archive apis 2026-04-27 17:05:08 +05:00
github-actions[bot]
3ac6263035 🔄 Update image to 131 [CI SKIP] 2026-04-27 12:01:46 +00:00
2c6d7dd2f7 Merge pull request 'fix 500 error' (#112) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m24s
Reviewed-on: #112
2026-04-27 11:59:43 +00:00
xoliqberdiyev
a6e0fca165 fix 500 error 2026-04-27 16:59:21 +05:00
github-actions[bot]
b64073e1ad 🔄 Update image to 130 [CI SKIP] 2026-04-27 11:54:31 +00:00
e3ffdddc46 Merge pull request 'resolve the error' (#111) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m8s
Reviewed-on: #111
2026-04-27 11:52:47 +00:00
xoliqberdiyev
6f48632e2d resolve the error 2026-04-27 16:52:30 +05:00
faea9bdb89 Merge pull request 'changing code structure' (#110) from behruz into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 56s
Reviewed-on: #110
2026-04-27 11:49:40 +00:00
xoliqberdiyev
e3e7f18d7f changing code structure 2026-04-27 16:49:07 +05:00
github-actions[bot]
1dd1a132e4 🔄 Update image to 128 [CI SKIP] 2026-04-27 09:54:08 +00:00
04e193bae6 Merge pull request 'add new api' (#109) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m7s
Reviewed-on: #109
2026-04-27 09:52:24 +00:00
xoliqberdiyev
7134b2c185 add new api 2026-04-27 14:50:59 +05:00
github-actions[bot]
306aecc956 🔄 Update image to 127 [CI SKIP] 2026-04-27 09:47:57 +00:00
3ede209e52 Merge pull request 'update' (#108) from shaxob into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 4m21s
Reviewed-on: #108
2026-04-27 09:46:13 +00:00
Shaxobff
05857a227a update 2026-04-27 14:45:32 +05:00
10b25b5228 Merge pull request 'update' (#107) from shaxob into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 3m43s
Reviewed-on: #107
2026-04-27 09:39:46 +00:00
Shaxobff
fcbfa94dd4 update 2026-04-27 14:38:55 +05:00
7e778d3a3e Merge pull request 'shaxob' (#106) from shaxob into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 10m36s
Reviewed-on: #106
2026-04-27 09:02:37 +00:00
Shaxobff
81a4287db1 update 2026-04-27 11:57:27 +05:00
Shaxobff
e560fdaf2d fix bug 2026-04-27 11:28:18 +05:00
Shaxobff
0d96167a7b fix bug 2026-04-27 10:58:02 +05:00
Shaxobff
ae65d9d793 resolve migrations conflict 2026-04-25 12:52:15 +05:00
github-actions[bot]
eded642bd7 🔄 Update image to 124 [CI SKIP] 2026-04-24 13:57:50 +00:00
f830235813 Merge pull request 'fix' (#105) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m15s
Reviewed-on: #105
2026-04-24 13:55:58 +00:00
xoliqberdiyev
a62cf3a1ee fix 2026-04-24 18:55:42 +05:00
github-actions[bot]
2f471173c3 🔄 Update image to 123 [CI SKIP] 2026-04-24 13:52:45 +00:00
3838fbaa47 Merge pull request 'change ci/cd folder' (#104) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m16s
Reviewed-on: #104
2026-04-24 13:50:51 +00:00
xoliqberdiyev
b02078e618 cha 2026-04-24 18:49:34 +05:00
xoliqberdiyev
1f59347d87 fix 2026-04-24 18:42:11 +05:00
github-actions[bot]
fe40057d95 🔄 Update image to 122 [CI SKIP] 2026-04-24 13:40:38 +00:00
550da049b9 Merge pull request 'fix' (#103) from behruz into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m17s
Reviewed-on: #103
2026-04-24 13:38:42 +00:00
xoliqberdiyev
bdd5aa9ce2 fix 2026-04-24 18:36:39 +05:00
github-actions[bot]
bd27205252 🔄 Update image to 121 [CI SKIP] 2026-04-24 13:34:27 +00:00
34aba90ebd Merge pull request 'behruz' (#102) from behruz into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m6s
Reviewed-on: #102
2026-04-24 13:32:26 +00:00
xoliqberdiyev
260bc9101e Merge branch 'main' of https://gitea.felixits.uz/sifatbaho/backend-v1 into behruz 2026-04-24 18:30:52 +05:00
xoliqberdiyev
f46dac515a fix 2026-04-24 18:30:41 +05:00
github-actions[bot]
c6fc150162 🔄 Update image to 120 [CI SKIP] 2026-04-24 12:57:55 +00:00
7272ef3fce Merge pull request 'fix migrations error' (#101) from behruz into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m3s
Reviewed-on: #101
2026-04-24 12:56:01 +00:00
xoliqberdiyev
1db936126d fix migrations error 2026-04-24 17:55:19 +05:00
5e1b02064e Merge pull request 'UPDATE' (#100) from shaxob into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 1m55s
Reviewed-on: #100
2026-04-24 12:37:17 +00:00
bcb453d52a Merge pull request 'UPDATE' (#98) from shaxob into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 1m51s
Reviewed-on: #98
2026-04-24 12:27:09 +00:00
039ca92031 Merge pull request 'behruz' (#99) from behruz into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 1m0s
Reviewed-on: #99
2026-04-24 12:25:44 +00:00
xoliqberdiyev
21bb61e51c change ci/cd 2026-04-24 17:24:34 +05:00
1ad2016790 Merge pull request 'shaxob' (#97) from shaxob into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 49s
Reviewed-on: #97
2026-04-24 11:40:31 +00:00
xoliqberdiyev
2b5238f3c8 add new api 2026-04-24 15:25:57 +05:00
xoliqberdiyev
988d07f4b6 Merge branch 'main' of https://gitea.felixits.uz/sifatbaho/backend-v1 2026-04-24 15:09:16 +05:00
xoliqberdiyev
7961fd76de add grpc client 2026-04-23 17:36:43 +05:00
85 changed files with 1889 additions and 646 deletions

View File

@@ -75,7 +75,3 @@ STORAGE_PROTOCOL=http:
# Didox configs # Didox configs
DIDOX_PARTNER_TOKEN=... DIDOX_PARTNER_TOKEN=...
# Celery configs

View File

@@ -8,7 +8,6 @@ on:
env: env:
PROJECT_NAME: sifatbaho PROJECT_NAME: sifatbaho
permissions: permissions:
contents: write contents: write
@@ -48,6 +47,24 @@ jobs:
- name: Copy env - name: Copy env
run: | run: |
cp .env.example .env cp .env.example .env
update_env() {
local env_file=".env"
for kv in "$@"; do
local key="${kv%%=*}"
local value="${kv#*=}"
if grep -q "^$key=" "$env_file"; then
sed -i "s|^$key=.*|$key=$value|" "$env_file"
else
echo "$key=$value" >> "$env_file"
fi
done
}
update_env \
"DB_HOST=postgres" \
"DB_NAME=sifatbahodb" \
"DB_PORT=5432" \
"DIDOX_PARTNER_TOKEN=${{ secrets.DIDOX_TOKEN }}"
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
@@ -95,7 +112,6 @@ jobs:
sed -i "s|image: .*/${{ env.PROJECT_NAME }}:.*|image: ${{ secrets.DOCKER_USERNAME }}/${{ env.PROJECT_NAME }}:${{ github.run_number }}|g" stack.yaml sed -i "s|image: .*/${{ env.PROJECT_NAME }}:.*|image: ${{ secrets.DOCKER_USERNAME }}/${{ env.PROJECT_NAME }}:${{ github.run_number }}|g" stack.yaml
sed -i 's/return HttpResponse("OK.*"/return HttpResponse("OK: #${{ github.sha }}"/' config/urls.py sed -i 's/return HttpResponse("OK.*"/return HttpResponse("OK: #${{ github.sha }}"/' config/urls.py
- name: Commit and push updated version - name: Commit and push updated version
run: | run: |
git config user.name "github-actions[bot]" git config user.name "github-actions[bot]"
@@ -136,24 +152,5 @@ jobs:
git reset --hard origin/main git reset --hard origin/main
cp .env.example .env cp .env.example .env
update_env() {
local env_file=".env"
for kv in "$@"; do
local key="${kv%%=*}"
local value="${kv#*=}"
if grep -q "^$key=" "$env_file"; then
sed -i "s|^$key=.*|$key=$value|" "$env_file"
else
echo "$key=$value" >> "$env_file"
fi
done
}
update_env \
"DB_HOST=postgres" \
"DB_NAME=sifatbahodb" \
"DB_PORT=5432" \
"DIDOX_TOKEN=${{ secrets.DIDOX_TOKEN }}"
export PORT=8085 export PORT=8085
docker stack deploy -c stack.yaml ${{ env.PROJECT_NAME }} --with-registry-auth docker stack deploy -c stack.yaml ${{ env.PROJECT_NAME }} --with-registry-auth

View File

@@ -14,6 +14,7 @@ APPS = [
"rest_framework_simplejwt", "rest_framework_simplejwt",
"django_core", "django_core",
"core.apps.accounts.apps.AccountsConfig", "core.apps.accounts.apps.AccountsConfig",
'core.apps.tasks.apps.TasksConfig',
] ]
if env.bool("SILK_ENABLED", False): if env.bool("SILK_ENABLED", False):

View File

@@ -186,5 +186,57 @@ PAGES = [
"link": reverse_lazy("admin:shared_villagemodel_changelist"), "link": reverse_lazy("admin:shared_villagemodel_changelist"),
}, },
] ]
},
{
"title": _("Ruxsatlar"),
"separator": True,
"items": [
{
"title": _("Ruxsatlar"),
"icon": "attach_file",
"link": reverse_lazy("admin:accounts_permission_changelist"),
},
{
"title": _("Sahifa uchun ruxsatlar"),
"icon": "attach_file",
"link": reverse_lazy("admin:accounts_permissiontotab_changelist"),
},
{
"title": _("Actionlar uchun ruxsatlar"),
"icon": "attach_file",
"link": reverse_lazy("admin:accounts_permissiontoaction_changelist"),
},
{
"title": _("Role"),
"icon": "attach_file",
"link": reverse_lazy("admin:accounts_role_changelist"),
},
]
},
{
"title": _("Task Management"),
"separator": True,
"items": [
{
"title": _("Task"),
"icon": "task",
"link": reverse_lazy("admin:tasks_task_changelist"),
},
{
"title": _("Column"),
"icon": "tag",
"link": reverse_lazy("admin:tasks_column_changelist"),
},
{
"title": _("Comment"),
"icon": "message",
"link": reverse_lazy("admin:tasks_comment_changelist"),
},
{
"title": _("Label"),
"icon": "tag",
"link": reverse_lazy("admin:tasks_label_changelist"),
},
]
} }
] ]

View File

@@ -13,7 +13,7 @@ from config.env import env
def home(request): def home(request):
return HttpResponse("OK: #88dedd85c79ccf732b2adac03616bd14e67a1579") return HttpResponse("OK: #65ab51e65224a92a4b6d488d3e8f9b21d3256876")
urlpatterns = [ urlpatterns = [
@@ -23,6 +23,7 @@ urlpatterns = [
path("api/v1/", include("core.apps.evaluation.urls")), path("api/v1/", include("core.apps.evaluation.urls")),
path("api/v1/", include("core.apps.payment.urls")), path("api/v1/", include("core.apps.payment.urls")),
path("api/v1/", include("core.apps.chat.urls")), path("api/v1/", include("core.apps.chat.urls")),
path("api/v1/tasks/", include("core.apps.tasks.urls")),
] ]
urlpatterns += [ urlpatterns += [
path("admin/", admin.site.urls), path("admin/", admin.site.urls),

View File

@@ -1,2 +1,3 @@
from .core import * # noqa from .core import * # noqa
from .user import * # noqa from .user import * # noqa
from .permission import *

View File

@@ -0,0 +1,77 @@
from django.contrib import admin
from core.apps.accounts.models.permission import (
PermissionToAction,
PermissionToTab,
Permission,
Role,
)
@admin.register(PermissionToAction)
class PermissionToActionAdmin(admin.ModelAdmin):
list_display = ("id", "name", "code", "created_at")
search_fields = ("name", "code")
fieldsets = (
("Asosiy", {
"fields": ("name", "code"),
}),
)
@admin.register(PermissionToTab)
class PermissionToTabAdmin(admin.ModelAdmin):
list_display = ("id", "name", "code", "created_at")
search_fields = ("name", "code")
filter_horizontal = ("permission_to_actions",)
fieldsets = (
("Asosiy", {
"fields": ("name", "code"),
}),
("Harakatlar", {
"fields": ("permission_to_actions",),
}),
)
@admin.register(Permission)
class PermissionAdmin(admin.ModelAdmin):
list_display = ("id", "name", "code", "created_at")
search_fields = ("name", "code")
filter_horizontal = ("permission_tabs",)
fieldsets = (
("Asosiy", {
"fields": ("name", "code"),
}),
("Boglanishlar", {
"fields": ("permission_tabs",),
}),
)
@admin.register(Role)
class RoleAdmin(admin.ModelAdmin):
list_display = ("id", "name")
search_fields = ("name",)
filter_horizontal = (
"permissions",
"permission_to_tabs",
"permission_to_actions",
)
fieldsets = (
("Asosiy ma'lumotlar", {
"fields": ("name", "comment"),
}),
("Sahifa ruxsatlari", {
"fields": ("permissions",),
}),
("Bolim ruxsatlari", {
"fields": ("permission_to_tabs",),
}),
("Harakat ruxsatlari", {
"fields": ("permission_to_actions",),
}),
)

View File

@@ -1,4 +1,5 @@
from django.contrib.auth import admin from django.contrib.auth import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from unfold.admin import ModelAdmin from unfold.admin import ModelAdmin

View File

@@ -1,4 +1,4 @@
# Generated by Django 5.2.7 on 2026-04-24 12:33 # Generated by Django 5.2.7 on 2026-04-27 09:33
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models from django.db import migrations, models
@@ -73,6 +73,6 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='user', model_name='user',
name='permission', name='permission',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.role'), field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='users', to='accounts.role'),
), ),
] ]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.7 on 2026-04-28 11:02
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('accounts', '0004_permissiontoaction_permissiontotab_permission_role_and_more'),
]
operations = [
migrations.RenameField(
model_name='permission',
old_name='permission_tab',
new_name='permission_tabs',
),
]

View File

@@ -33,7 +33,7 @@ class PermissionToTab(AbstractBaseModel):
class Permission(AbstractBaseModel): class Permission(AbstractBaseModel):
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
code = models.CharField(max_length=100, unique=True) code = models.CharField(max_length=100, unique=True)
permission_tab = models.ManyToManyField(PermissionToTab, related_name='permissions') permission_tabs = models.ManyToManyField(PermissionToTab, related_name='permissions')
def __str__(self): def __str__(self):
return f'{self.name} - {self.code}' return f'{self.name} - {self.code}'

View File

@@ -18,7 +18,7 @@ class User(auth_models.AbstractUser):
default=RoleChoice.USER, default=RoleChoice.USER,
) )
avatar = models.ImageField(upload_to="avatars/", null=True, blank=True) avatar = models.ImageField(upload_to="avatars/", null=True, blank=True)
permission = models.ForeignKey(Role, on_delete=models.SET_NULL, null=True) permission = models.ForeignKey(Role, on_delete=models.SET_NULL, null=True, blank=True, related_name='users')
USERNAME_FIELD = "phone" USERNAME_FIELD = "phone"
objects = UserManager() objects = UserManager()

View File

@@ -0,0 +1,15 @@
from rest_framework.exceptions import PermissionDenied
from rest_framework.permissions import BasePermission
from core.apps.accounts.choices import RoleChoice
class IsAdminRole(BasePermission):
def has_permission(self, request, view):
if not request.user.is_authenticated:
return False
if request.user.role != RoleChoice.ADMIN:
raise PermissionDenied("Only admin can access this")
return True

View File

@@ -6,21 +6,50 @@ from core.apps.accounts.models.permission import PermissionToAction, PermissionT
class PermissionToActionSerializer(serializers.ModelSerializer): class PermissionToActionSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = PermissionToAction model = PermissionToAction
fields = "__all__" fields = ['id', 'name']
class PermissionToTabSerializer(serializers.ModelSerializer): class PermissionToTabSerializer(serializers.ModelSerializer):
permission_to_actions = PermissionToActionSerializer(many=True, read_only=True)
class Meta: class Meta:
model = PermissionToTab model = PermissionToTab
fields = '__all__' fields = ['id', 'name', 'permission_to_actions']
class PermissionSerializer(serializers.ModelSerializer): class PermissionSerializer(serializers.ModelSerializer):
permission_tabs = PermissionToTabSerializer(many=True, read_only=True)
class Meta: class Meta:
model = Permission model = Permission
fields = '__all__' fields = ['id', 'name', 'permission_tabs']
class RoleSerializer(serializers.ModelSerializer): class PermissionToActionListSerializer(serializers.ModelSerializer):
class Meta:
model = PermissionToAction
fields = ['id', 'name']
class PermissionToTabListSerializer(serializers.ModelSerializer):
class Meta:
model = PermissionToTab
fields = ['id', 'name']
class PermissionListSerializer(serializers.ModelSerializer):
class Meta:
model = Permission
fields = ['id', 'name']
class RoleListSerializer(serializers.ModelSerializer):
permissions = PermissionListSerializer(many=True)
permission_to_tabs = PermissionToTabListSerializer(many=True)
permission_to_actions = PermissionToActionListSerializer(many=True)
class Meta: class Meta:
model = Role model = Role
fields = '__all__' fields = [
'id', 'name', 'comment', 'permissions', 'permission_to_tabs', 'permission_to_actions',
]

View File

@@ -54,4 +54,22 @@ class UserCreateSerializer(serializers.ModelSerializer):
"first_name", "first_name",
"last_name", "last_name",
"password", "password",
"role"] "role"
]
class ShortUserSerializer(serializers.ModelSerializer):
class Meta:
model = get_user_model()
fields = [
'id',
'first_name',
'last_name',
'avatar',
]
def get_avatar(self, obj):
request = self.context.get('request')
if obj.avatar:
return request.build_absolute_uri(obj.avatar.url)
return None

View File

@@ -9,6 +9,7 @@ from .views import RegisterView, ResetPasswordView, MeView, ChangePasswordView,
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from .views.permission import PermissionToActionViewSet, PermissionToTabViewSet, PermissionViewSet, RoleViewSet from .views.permission import PermissionToActionViewSet, PermissionToTabViewSet, PermissionViewSet, RoleViewSet
from core.apps.accounts.views.user import DeleteAdminUserApiView, UserDetailAPIView
router = DefaultRouter() router = DefaultRouter()
router.register("auth", RegisterView, basename="auth") router.register("auth", RegisterView, basename="auth")
@@ -26,13 +27,11 @@ urlpatterns = [
path("", include(router.urls)), path("", include(router.urls)),
path("auth/token/", jwt_views.TokenObtainPairView.as_view(), name="token_obtain_pair"), path("auth/token/", jwt_views.TokenObtainPairView.as_view(), name="token_obtain_pair"),
path("auth/token/verify/", jwt_views.TokenVerifyView.as_view(), name="token_verify"), path("auth/token/verify/", jwt_views.TokenVerifyView.as_view(), name="token_verify"),
path( path("auth/token/refresh/", jwt_views.TokenRefreshView.as_view()),
"auth/token/refresh/",
jwt_views.TokenRefreshView.as_view(),
name="token_refresh",
),
path("user/list/", UserListApiView.as_view(), name="user-list"), path("user/list/", UserListApiView.as_view(), name="user-list"),
path("admin-user/list/", AdminUserListApiView.as_view(), name="admin-user-list"), path("admin-user/list/", AdminUserListApiView.as_view(), name="admin-user-list"),
path("admin/create/", AdminCreateAPIView.as_view(), name="user-create"), path("admin/create/", AdminCreateAPIView.as_view(), name="user-create"),
path("admin/update/", AdminUpdateAPIView.as_view(), name="user-update"), path("admin/update/<int:pk>/", AdminUpdateAPIView.as_view(), name="user-update"),
path('user/admin/<int:pk>/delete/', DeleteAdminUserApiView.as_view(), name='user-delete'),
path('user/<int:pk>/', UserDetailAPIView.as_view(), name='user-detail'),
] ]

View File

@@ -5,7 +5,7 @@ from rest_framework.viewsets import ModelViewSet
from core.apps.accounts.models.permission import PermissionToAction, PermissionToTab, Permission, Role from core.apps.accounts.models.permission import PermissionToAction, PermissionToTab, Permission, Role
from core.apps.accounts.serializers.permission import PermissionToActionSerializer, PermissionToTabSerializer, \ from core.apps.accounts.serializers.permission import PermissionToActionSerializer, PermissionToTabSerializer, \
PermissionSerializer, RoleSerializer PermissionSerializer, RoleListSerializer
@extend_schema(tags=["permission"]) @extend_schema(tags=["permission"])
@@ -30,7 +30,6 @@ class PermissionToTabViewSet(BaseViewSetMixin, ModelViewSet):
serializer_class = PermissionToTabSerializer serializer_class = PermissionToTabSerializer
@extend_schema(tags=["permission"]) @extend_schema(tags=["permission"])
class PermissionViewSet(BaseViewSetMixin, ModelViewSet): class PermissionViewSet(BaseViewSetMixin, ModelViewSet):
queryset = Permission.objects.all() queryset = Permission.objects.all()
@@ -39,4 +38,4 @@ class PermissionViewSet(BaseViewSetMixin, ModelViewSet):
class RoleViewSet(BaseViewSetMixin, ModelViewSet): class RoleViewSet(BaseViewSetMixin, ModelViewSet):
queryset = Role.objects.all() queryset = Role.objects.all()
serializer_class = RoleSerializer serializer_class = RoleListSerializer

View File

@@ -9,6 +9,8 @@ from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from core.apps.accounts.choices.user import RoleChoice from core.apps.accounts.choices.user import RoleChoice
from core.apps.accounts.models import Role
from core.apps.accounts.serializers.permission import RoleListSerializer
from core.apps.accounts.serializers.user import UserSerializer, AdminUserSerializer, UserCreateSerializer from core.apps.accounts.serializers.user import UserSerializer, AdminUserSerializer, UserCreateSerializer
User = get_user_model() User = get_user_model()
@@ -64,11 +66,10 @@ class AdminCreateAPIView(APIView):
return Response(serializer.data, status=201) return Response(serializer.data, status=201)
@extend_schema(tags=['User'], @extend_schema(tags=['User'], )
responses={200: UserSerializer}, class AdminUpdateAPIView(generics.GenericAPIView):
request=UserCreateSerializer)
class AdminUpdateAPIView(APIView):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
serializer_class = UserCreateSerializer
def put(self, request, pk): def put(self, request, pk):
if request.user.role not in (RoleChoice.SUPERUSER, RoleChoice.ADMIN): if request.user.role not in (RoleChoice.SUPERUSER, RoleChoice.ADMIN):
@@ -80,3 +81,38 @@ class AdminUpdateAPIView(APIView):
serializer.save() serializer.save()
return Response(serializer.data, status=200) return Response(serializer.data, status=200)
class DeleteAdminUserApiView(APIView):
permission_classes = [IsAuthenticated]
def delete(self, request, pk):
if request.user.role != RoleChoice.SUPERUSER:
return Response({'detail': 'Forbidden'}, status=403)
user = get_object_or_404(User, pk=pk)
if user.role != RoleChoice.ADMIN:
return Response({'detail': 'This user is not an admin'}, status=400)
user.delete()
return Response(status=204)
class UserDetailAPIView(generics.RetrieveAPIView):
permission_classes = [IsAuthenticated]
serializer_class = UserSerializer
lookup_field = 'id'
class AdminPermissionsAPIView(generics.GenericAPIView):
permission_classes = [IsAuthenticated]
queryset = User.objects.all()
def get(self, request):
if request.user.role.name != RoleChoice.ADMIN:
return Response({'detail': 'Forbidden'}, status=403)
admin_role = Role.objects.get(name=RoleChoice.ADMIN)
serializer = RoleListSerializer(admin_role)
return Response(serializer.data)

View File

@@ -19,3 +19,8 @@ class RequestStatus(models.TextChoices):
IN_PROGRESS = "in_progress", _("Jarayonda") IN_PROGRESS = "in_progress", _("Jarayonda")
COMPLETED = "completed", _("Bajarildi") COMPLETED = "completed", _("Bajarildi")
REJECTED = "rejected", _("Rad etildi") REJECTED = "rejected", _("Rad etildi")
class RequestPersonType(models.TextChoices):
INDIVIDUAL_PERSON = "individual_person", "Jismoniy shaxs"
LEGAL_PERSON = "legal_person", 'Yuridik shaxs',

View File

@@ -1,4 +1,4 @@
# Generated by Django 5.2.7 on 2026-04-24 12:33 # Generated by Django 5.2.7 on 2026-04-27 09:33
from django.db import migrations, models from django.db import migrations, models

View File

@@ -0,0 +1,53 @@
# Generated by Django 5.2.7 on 2026-04-28 11:07
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0035_autoevaluationmodel_is_archived'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RemoveField(
model_name='autoevaluationmodel',
name='form_ownership',
),
migrations.RemoveField(
model_name='autoevaluationmodel',
name='property_rights',
),
migrations.RemoveField(
model_name='autoevaluationmodel',
name='rate_object_name',
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='appraisers',
field=models.ManyToManyField(blank=True, null=True, to=settings.AUTH_USER_MODEL, verbose_name='appraisers'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='evaluation_request',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='auto_evaluations_request', to='evaluation.evaluationrequestmodel'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='auto_evaluations_user', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='valuation',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='auto_detail', to='evaluation.valuationmodel'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='vehicle',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='evaluation', to='evaluation.vehiclemodel'),
),
]

View File

@@ -0,0 +1,49 @@
# Generated by Django 5.2.7 on 2026-04-28 11:41
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0036_remove_autoevaluationmodel_form_ownership_and_more'),
]
operations = [
migrations.AddField(
model_name='evaluationrequestmodel',
name='customer_and_owner_same',
field=models.BooleanField(default=False),
),
migrations.CreateModel(
name='EvaluationRequestCustomerModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('type', models.CharField(choices=[('individual_person', 'Jismoniy shaxs'), ('legal_person', 'Yuridik shaxs')], max_length=100)),
('jshshir', models.CharField(max_length=100)),
('evaluation_request', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='customer', to='evaluation.evaluationrequestmodel')),
],
options={
'verbose_name': 'Evaluation Request Customer',
'verbose_name_plural': 'Evaluation Request Customers',
},
),
migrations.CreateModel(
name='EvaluationRequestOwnerModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('type', models.CharField(choices=[('individual_person', 'Jismoniy shaxs'), ('legal_person', 'Yuridik shaxs')], max_length=100)),
('jshshir', models.CharField(max_length=100)),
('evaluation_request', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='owner', to='evaluation.evaluationrequestmodel')),
],
options={
'verbose_name': 'Evaluation Request Owner',
'verbose_name_plural': 'Evaluation Request Owners',
},
),
]

View File

@@ -0,0 +1,88 @@
# Generated by Django 5.2.7 on 2026-04-28 11:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0037_evaluationrequestmodel_customer_and_owner_same_and_more'),
]
operations = [
migrations.AddField(
model_name='evaluationrequestmodel',
name='distance_covered',
field=models.FloatField(blank=True, default=0.0, null=True),
),
migrations.AddField(
model_name='evaluationrequestmodel',
name='gov_number',
field=models.CharField(blank=True, max_length=100, null=True),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='chassi',
field=models.CharField(blank=True, max_length=100, null=True),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='customer_inn_number',
field=models.CharField(max_length=20),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='is_archive',
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='location_lat',
field=models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='location_lng',
field=models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='location_name',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='need_delivering',
field=models.BooleanField(default=True),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='object_type',
field=models.CharField(blank=True, choices=[('lightweight_auto', 'Yengil automobil'), ('truck_car', 'Yuk automobil'), ('special_tech', 'Maxsus texnika')], max_length=50, null=True),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='owner_inn_number',
field=models.CharField(max_length=20),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='rate_type',
field=models.CharField(choices=[('auto', 'Automobil'), ('real_estate', "Ko'chmas mulk"), ('equipment', 'Uskuna')], max_length=50),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='status',
field=models.CharField(choices=[('pending', 'Kutilmoqda'), ('in_progress', 'Jarayonda'), ('completed', 'Bajarildi'), ('rejected', 'Rad etildi')], default='pending', max_length=50),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='tex_passport',
field=models.CharField(blank=True, max_length=20, null=True),
),
migrations.AlterField(
model_name='evaluationrequestmodel',
name='worked_hours',
field=models.IntegerField(blank=True, null=True),
),
]

View File

@@ -26,7 +26,6 @@ class AutoEvaluationModel(AbstractBaseModel):
"accounts.User", "accounts.User",
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
related_name="auto_evaluations_user", related_name="auto_evaluations_user",
verbose_name=_("user"),
null=True, null=True,
blank=True, blank=True,
) )
@@ -34,7 +33,6 @@ class AutoEvaluationModel(AbstractBaseModel):
"evaluation.EvaluationRequestModel", "evaluation.EvaluationRequestModel",
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
related_name="auto_evaluations_request", related_name="auto_evaluations_request",
verbose_name=_("evaluation request"),
null=True, null=True,
blank=True, blank=True,
) )
@@ -42,7 +40,6 @@ class AutoEvaluationModel(AbstractBaseModel):
ValuationModel, ValuationModel,
on_delete=models.CASCADE, on_delete=models.CASCADE,
related_name="auto_detail", related_name="auto_detail",
verbose_name=_("valuation"),
null=True, null=True,
blank=True, blank=True,
) )
@@ -50,14 +47,12 @@ class AutoEvaluationModel(AbstractBaseModel):
VehicleModel, VehicleModel,
on_delete=models.CASCADE, on_delete=models.CASCADE,
related_name="evaluation", related_name="evaluation",
verbose_name=_("vehicle"),
null=True, null=True,
blank=True, blank=True,
) )
appraisers = models.ManyToManyField( appraisers = models.ManyToManyField(
"accounts.User", "accounts.User",
verbose_name=_("appraisers"), verbose_name=_("appraisers"),
related_name="auto_evaluations",
blank=True, blank=True,
null=True, null=True,
) )
@@ -96,12 +91,6 @@ class AutoEvaluationModel(AbstractBaseModel):
blank=True, blank=True,
null=True, null=True,
) )
rate_object_name = models.CharField(
verbose_name=_("rate object name"),
max_length=255,
blank=True,
null=True,
)
object_type = models.CharField( object_type = models.CharField(
verbose_name=_("object type"), verbose_name=_("object type"),
max_length=50, max_length=50,
@@ -153,23 +142,6 @@ class AutoEvaluationModel(AbstractBaseModel):
blank=True, blank=True,
null=True, null=True,
) )
property_rights = models.ForeignKey(
'evaluation.ReferenceitemModel',
verbose_name=_("property rights"),
blank=True,
null=True,
on_delete=models.SET_NULL,
related_name='evaluation_auto_property_rights'
)
form_ownership = models.ForeignKey(
'evaluation.ReferenceitemModel',
verbose_name=_("form of ownership"),
blank=True,
null=True,
on_delete=models.SET_NULL,
related_name='evaluation_auto_form_ownership'
)
value_determined = models.ForeignKey( value_determined = models.ForeignKey(
'evaluation.ReferenceitemModel', 'evaluation.ReferenceitemModel',
verbose_name=_("value determined"), verbose_name=_("value determined"),

View File

@@ -8,43 +8,41 @@ from core.apps.evaluation.choices.request import (
EvaluationRateType, EvaluationRateType,
RequestObjectType, RequestObjectType,
RequestStatus, RequestStatus,
RequestPersonType,
) )
from core.apps.evaluation.models import ReferenceitemModel from core.apps.evaluation.models import ReferenceitemModel
class EvaluationrequestModel(AbstractBaseModel): class EvaluationrequestModel(AbstractBaseModel):
rate_type = models.CharField(max_length=50,choices=EvaluationRateType.choices)
object_type = models.CharField(max_length=50,choices=RequestObjectType.choices,blank=True,null=True)
status = models.CharField(max_length=50, choices=RequestStatus.choices, default=RequestStatus.PENDING)
distance_covered = models.FloatField(default=0.0, null=True, blank=True)
worked_hours = models.IntegerField(blank=True,null=True)
customer_inn_number = models.CharField(max_length=20)
owner_inn_number = models.CharField(max_length=20)
tex_passport = models.CharField(max_length=20,blank=True,null=True)
chassi = models.CharField(max_length=100,blank=True,null=True)
gov_number = models.CharField(max_length=100, null=True, blank=True)
location_name = models.CharField(max_length=255,blank=True,null=True)
location_lat = models.DecimalField(max_digits=9,decimal_places=6,blank=True, null=True)
location_lng = models.DecimalField(max_digits=9,decimal_places=6,blank=True,null=True)
need_delivering = models.BooleanField(default=True)
is_archive = models.BooleanField(default=False)
customer_and_owner_same = models.BooleanField(default=False)
###################
# Foreign Keys
###################
user = models.ForeignKey( user = models.ForeignKey(
"accounts.User", "accounts.User",
on_delete=models.CASCADE, on_delete=models.CASCADE,
related_name="evaluation_requests", related_name="evaluation_requests",
verbose_name=_("user"), verbose_name=_("user"),
) )
rate_type = models.CharField(
verbose_name=_("rate type"),
max_length=50,
choices=EvaluationRateType.choices,
)
object_type = models.CharField(
verbose_name=_("object type"),
max_length=50,
choices=RequestObjectType.choices,
blank=True,
null=True,
)
customer_inn_number = models.CharField(
verbose_name=_("customer INN number"),
max_length=20,
)
owner_inn_number = models.CharField(
verbose_name=_("owner INN number"),
max_length=20,
)
tex_passport = models.CharField(
verbose_name=_("tex passport"),
max_length=20,
blank=True,
null=True,
)
value_determined = models.ForeignKey( value_determined = models.ForeignKey(
"evaluation.ReferenceitemModel", "evaluation.ReferenceitemModel",
verbose_name=_("value determined"), verbose_name=_("value determined"),
@@ -77,51 +75,8 @@ class EvaluationrequestModel(AbstractBaseModel):
blank=True, blank=True,
null=True, null=True,
) )
worked_hours = models.IntegerField(
verbose_name=_("worked hours"),
blank=True,
null=True,
)
chassi = models.CharField(
verbose_name=_("chassi"),
max_length=100,
blank=True,
null=True,
)
need_delivering = models.BooleanField(
verbose_name=_("need delivering"),
default=True,
)
location_name = models.CharField(
verbose_name=_("location name"),
max_length=255,
blank=True,
null=True,
)
location_lat = models.DecimalField(
verbose_name=_("location latitude"),
max_digits=9,
decimal_places=6,
blank=True,
null=True,
)
location_lng = models.DecimalField(
verbose_name=_("location longitude"),
max_digits=9,
decimal_places=6,
blank=True,
null=True,
)
status = models.CharField(
verbose_name=_("status"),
max_length=50,
choices=RequestStatus.choices,
default=RequestStatus.PENDING,
)
is_archive = models.BooleanField(
verbose_name=_("is archive"),
default=False,
)
def __str__(self): def __str__(self):
return f"Requests #{self.pk}{self.get_rate_type_display()}" return f"Requests #{self.pk}{self.get_rate_type_display()}"
@@ -147,3 +102,29 @@ class EvaluationrequestModel(AbstractBaseModel):
db_table = "EvaluationRequest" db_table = "EvaluationRequest"
verbose_name = _("Evaluation Request") verbose_name = _("Evaluation Request")
verbose_name_plural = _("Evaluation Requests") verbose_name_plural = _("Evaluation Requests")
class EvaluationRequestOwnerModel(AbstractBaseModel):
evaluation_request = models.OneToOneField(EvaluationrequestModel, on_delete=models.CASCADE, related_name='owner')
type = models.CharField(max_length=100, choices=RequestPersonType.choices)
jshshir = models.CharField(max_length=100)
def __str__(self):
return f"Owner #{self.pk}{self.type}"
class Meta:
verbose_name = _("Evaluation Request Owner")
verbose_name_plural = _("Evaluation Request Owners")
class EvaluationRequestCustomerModel(AbstractBaseModel):
evaluation_request = models.OneToOneField(EvaluationrequestModel, on_delete=models.CASCADE, related_name='customer')
type = models.CharField(max_length=100, choices=RequestPersonType.choices)
jshshir = models.CharField(max_length=100)
def __str__(self):
return f"Customer #{self.pk}{self.type}"
class Meta:
verbose_name = _("Evaluation Request Customer")
verbose_name_plural = _("Evaluation Request Customers")

View File

@@ -17,8 +17,6 @@ class BaseAutoevaluationSerializer(serializers.ModelSerializer):
default=None) default=None)
rate_type = ListReferenceitemSerializer(read_only=True) rate_type = ListReferenceitemSerializer(read_only=True)
value_determined = ListReferenceitemSerializer(read_only=True) value_determined = ListReferenceitemSerializer(read_only=True)
property_rights = ListReferenceitemSerializer(read_only=True)
form_ownership = ListReferenceitemSerializer(read_only=True)
user = serializers.SerializerMethodField(method_name="get_user", read_only=True) user = serializers.SerializerMethodField(method_name="get_user", read_only=True)
class Meta: class Meta:
@@ -49,8 +47,6 @@ class BaseAutoevaluationSerializer(serializers.ModelSerializer):
"created_at", "created_at",
"value_determined", "value_determined",
"rate_type", "rate_type",
"property_rights",
"form_ownership",
"user", "user",
"evaluation_request", "evaluation_request",
] ]
@@ -75,13 +71,6 @@ class RetrieveAutoevaluationSerializer(BaseAutoevaluationSerializer):
car_type_display = serializers.CharField(source="get_car_type_display", read_only=True, default=None) car_type_display = serializers.CharField(source="get_car_type_display", read_only=True, default=None)
car_wheel_display = serializers.CharField(source="get_car_wheel_display", read_only=True, default=None) car_wheel_display = serializers.CharField(source="get_car_wheel_display", read_only=True, default=None)
# object_location_highways_display = serializers.CharField(
# source="get_object_location_highways_display", read_only=True, default=None
# )
# object_location_covenience_display = serializers.CharField(
# source="get_object_location_covenience_display", read_only=True, default=None
# )
class Meta(BaseAutoevaluationSerializer.Meta): class Meta(BaseAutoevaluationSerializer.Meta):
fields = BaseAutoevaluationSerializer.Meta.fields + [ fields = BaseAutoevaluationSerializer.Meta.fields + [
# Step 1 # Step 1
@@ -89,7 +78,6 @@ class RetrieveAutoevaluationSerializer(BaseAutoevaluationSerializer):
"object_inspection_date", "object_inspection_date",
"rate_date", "rate_date",
"rate_report_date", "rate_report_date",
"rate_object_name",
# Step 2 # Step 2
"object_owner_type", "object_owner_type",
"object_owner_type_display", "object_owner_type_display",
@@ -118,21 +106,11 @@ class RetrieveAutoevaluationSerializer(BaseAutoevaluationSerializer):
class UpdateAutoevaluationSerializer(serializers.ModelSerializer): class UpdateAutoevaluationSerializer(serializers.ModelSerializer):
property_rights = serializers.PrimaryKeyRelatedField(
queryset=ReferenceitemModel.objects.all(),
required=False,
allow_null=True,
)
value_determined = serializers.PrimaryKeyRelatedField( value_determined = serializers.PrimaryKeyRelatedField(
queryset=ReferenceitemModel.objects.all(), queryset=ReferenceitemModel.objects.all(),
required=False, required=False,
allow_null=True, allow_null=True,
) )
form_ownership = serializers.PrimaryKeyRelatedField(
queryset=ReferenceitemModel.objects.all(),
required=False,
allow_null=True,
)
value_determined = serializers.PrimaryKeyRelatedField( value_determined = serializers.PrimaryKeyRelatedField(
queryset=ReferenceitemModel.objects.all(), queryset=ReferenceitemModel.objects.all(),
required=False, required=False,
@@ -153,7 +131,6 @@ class UpdateAutoevaluationSerializer(serializers.ModelSerializer):
"object_inspection_date", "object_inspection_date",
"rate_date", "rate_date",
"rate_report_date", "rate_report_date",
"rate_object_name",
"object_type", "object_type",
# Step 2 # Step 2
"object_owner_type", "object_owner_type",
@@ -163,8 +140,6 @@ class UpdateAutoevaluationSerializer(serializers.ModelSerializer):
"object_owner_individual_person_passport_num", "object_owner_individual_person_passport_num",
"object_owner_legal_entity", "object_owner_legal_entity",
"object_owner_legal_inn", "object_owner_legal_inn",
"property_rights",
"form_ownership",
"value_determined", "value_determined",
"rate_type", "rate_type",
# Step 4 # Step 4
@@ -226,21 +201,11 @@ class UpdateAutoevaluationSerializer(serializers.ModelSerializer):
class CreateAutoevaluationSerializer(serializers.ModelSerializer): class CreateAutoevaluationSerializer(serializers.ModelSerializer):
property_rights = serializers.PrimaryKeyRelatedField(
queryset=ReferenceitemModel.objects.all(),
required=False,
allow_null=True,
)
value_determined = serializers.PrimaryKeyRelatedField( value_determined = serializers.PrimaryKeyRelatedField(
queryset=ReferenceitemModel.objects.all(), queryset=ReferenceitemModel.objects.all(),
required=False, required=False,
allow_null=True, allow_null=True,
) )
form_ownership = serializers.PrimaryKeyRelatedField(
queryset=ReferenceitemModel.objects.all(),
required=False,
allow_null=True,
)
value_determined = serializers.PrimaryKeyRelatedField( value_determined = serializers.PrimaryKeyRelatedField(
queryset=ReferenceitemModel.objects.all(), queryset=ReferenceitemModel.objects.all(),
required=False, required=False,
@@ -267,7 +232,6 @@ class CreateAutoevaluationSerializer(serializers.ModelSerializer):
"object_inspection_date", "object_inspection_date",
"rate_date", "rate_date",
"rate_report_date", "rate_report_date",
"rate_object_name",
"object_type", "object_type",
# Step 2 # Step 2
"object_owner_type", "object_owner_type",
@@ -277,8 +241,6 @@ class CreateAutoevaluationSerializer(serializers.ModelSerializer):
"object_owner_individual_person_passport_num", "object_owner_individual_person_passport_num",
"object_owner_legal_entity", "object_owner_legal_entity",
"object_owner_legal_inn", "object_owner_legal_inn",
"property_rights",
"form_ownership",
"value_determined", "value_determined",
"rate_type", "rate_type",
# Step 4 # Step 4
@@ -359,6 +321,7 @@ class AutoEvaluationAppraisersSerializer(serializers.Serializer):
data['users'] = users data['users'] = users
return data return data
class AutoEvaluationSerializer(serializers.Serializer): class AutoEvaluationSerializer(serializers.Serializer):
brand = serializers.CharField() brand = serializers.CharField()
brand_model = serializers.CharField() brand_model = serializers.CharField()
@@ -368,3 +331,59 @@ class AutoEvaluationSerializer(serializers.Serializer):
condition = serializers.CharField() condition = serializers.CharField()
fuel_type = serializers.CharField() fuel_type = serializers.CharField()
mileage = serializers.CharField() mileage = serializers.CharField()
class AutoEvaluationModelSerializer(serializers.ModelSerializer):
user = serializers.StringRelatedField(read_only=True)
appraisers = serializers.PrimaryKeyRelatedField(
many=True,
queryset=User.objects.all(),
required=False
)
class Meta:
model = AutoEvaluationModel
fields = ("tex_passport_file",
"registration_number",
"contract_date",
"object_inspection_date",
"rate_date",
"rate_report_date",
"object_type",
"object_owner_type",
"object_owner_individual_person_f_name",
"object_owner_individual_person_l_name",
"object_owner_individual_person_p_name",
"object_owner_individual_person_passport_num",
"object_owner_legal_entity",
"object_owner_legal_inn",
"value_determined",
"rate_type",
"tex_passport_serie_num",
"tex_passport_gived_date",
"tex_passport_gived_location",
"car_type",
"car_wheel",
"car_brand",
"car_model",
"car_number",
"manufacture_year",
"car_dvigatel_number",
"car_color",
"rating_goal",
"status",
"is_archived",
"created_at",
"updated_at",
)
read_only_fields = (
"id",
"created_at",
"updated_at",
)

View File

@@ -0,0 +1,11 @@
from rest_framework import serializers
class AvgCostSerializer(serializers.Serializer):
brand = serializers.CharField(max_length=100)
condition = serializers.CharField(max_length=100)
model = serializers.CharField(max_length=100)
complication = serializers.CharField(max_length=100)
manufacture_date = serializers.DateField()
distance_covered = serializers.IntegerField()
color = serializers.CharField(max_length=100)

View File

@@ -3,6 +3,7 @@ from core.apps.evaluation.models import CertificateModel
class BaseCertificateSerializer(serializers.ModelSerializer): class BaseCertificateSerializer(serializers.ModelSerializer):
file = serializers.SerializerMethodField(method_name='get_file', read_only=True)
class Meta: class Meta:
model = CertificateModel model = CertificateModel
@@ -11,3 +12,19 @@ class BaseCertificateSerializer(serializers.ModelSerializer):
"title", "title",
"file", "file",
] ]
def get_file(self, obj):
if obj.file:
request = self.context.get('request')
return request.build_absolute_uri(obj.file.url)
return None
class CreateCertificateSerializer(serializers.ModelSerializer):
class Meta:
model = CertificateModel
fields = [
"id",
"title",
"file",
]

View File

@@ -128,6 +128,42 @@ class CreateQuickevaluationSerializer(serializers.ModelSerializer):
return super().create(validated_data) return super().create(validated_data)
class ArchiveQuickevaluationSerializer(serializers.Serializer): class QuickEvaluationModelSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=True) class Meta:
is_archive = serializers.BooleanField(required=True) model = QuickEvaluationModel
fields = (
"id",
"created_by",
"brand",
"marka",
"car_position",
"body_type",
"color",
"fuel_type",
"state_car",
"tex_passport_serie_num",
"tech_passport_issued_date",
"tech_passport_issued_place",
"car_type",
"distance_covered",
"vin_number",
"car_number",
"car_manufactured_date",
"engine_number",
"estimated_price",
"status",
"is_archive",
"created_at",
"updated_at",
)
read_only_fields = (
"id",
"created_at",
"updated_at",
)

View File

@@ -4,8 +4,11 @@ from django.contrib.auth import get_user_model
from rest_framework import serializers from rest_framework import serializers
from core.apps.evaluation.models import EvaluationrequestModel, ReferenceitemModel from core.apps.evaluation.models import EvaluationrequestModel, ReferenceitemModel, EvaluationRequestOwnerModel, EvaluationRequestCustomerModel
from core.apps.evaluation.serializers.reference import ListReferenceitemSerializer from core.apps.evaluation.serializers.reference import ListReferenceitemSerializer
from core.apps.evaluation.serializers.request.owner import EvaluationRequestOwnerSerializer
from core.apps.evaluation.serializers.request.req_customer import EvaluationRequestCustomerSerializer
User = get_user_model() User = get_user_model()
@@ -29,6 +32,8 @@ class BaseEvaluationrequestSerializer(serializers.ModelSerializer):
property_rights = ListReferenceitemSerializer(read_only=True) property_rights = ListReferenceitemSerializer(read_only=True)
form_ownership = ListReferenceitemSerializer(read_only=True) form_ownership = ListReferenceitemSerializer(read_only=True)
user = serializers.SerializerMethodField(method_name="get_user") user = serializers.SerializerMethodField(method_name="get_user")
customer = EvaluationRequestCustomerSerializer(read_only=True)
owner = EvaluationRequestOwnerSerializer(read_only=True)
class Meta: class Meta:
model = EvaluationrequestModel model = EvaluationrequestModel
@@ -56,6 +61,8 @@ class BaseEvaluationrequestSerializer(serializers.ModelSerializer):
"created_at", "created_at",
"updated_at", "updated_at",
"is_archive", "is_archive",
"customer",
"owner",
] ]
def get_location(self, obj): def get_location(self, obj):
@@ -92,7 +99,6 @@ class RetrieveEvaluationrequestSerializer(BaseEvaluationrequestSerializer):
class CreateEvaluationrequestSerializer(serializers.ModelSerializer): class CreateEvaluationrequestSerializer(serializers.ModelSerializer):
location = serializers.DictField(required=False, allow_empty=True) location = serializers.DictField(required=False, allow_empty=True)
# locationName — string qabul qiladi, location ichida yoki tashqarida yuborsa bo'ladi
locationName = serializers.CharField( locationName = serializers.CharField(
write_only=True, write_only=True,
required=False, required=False,
@@ -100,8 +106,6 @@ class CreateEvaluationrequestSerializer(serializers.ModelSerializer):
allow_blank=True, allow_blank=True,
) )
# Faqat truck_car uchun majburiy — field darajasida optional qilib belgilaymiz,
# validate() da object_type ga qarab tekshiramiz
worked_hours = serializers.IntegerField( worked_hours = serializers.IntegerField(
required=False, required=False,
allow_null=True, allow_null=True,
@@ -116,6 +120,8 @@ class CreateEvaluationrequestSerializer(serializers.ModelSerializer):
rate_goal = serializers.PrimaryKeyRelatedField(required=False, queryset=ReferenceitemModel.objects.all()) rate_goal = serializers.PrimaryKeyRelatedField(required=False, queryset=ReferenceitemModel.objects.all())
property_rights = serializers.PrimaryKeyRelatedField(required=False, queryset=ReferenceitemModel.objects.all()) property_rights = serializers.PrimaryKeyRelatedField(required=False, queryset=ReferenceitemModel.objects.all())
form_ownership = serializers.PrimaryKeyRelatedField(required=False, queryset=ReferenceitemModel.objects.all()) form_ownership = serializers.PrimaryKeyRelatedField(required=False, queryset=ReferenceitemModel.objects.all())
customer = EvaluationRequestCustomerSerializer()
owner = EvaluationRequestOwnerSerializer()
class Meta: class Meta:
model = EvaluationrequestModel model = EvaluationrequestModel
@@ -134,6 +140,11 @@ class CreateEvaluationrequestSerializer(serializers.ModelSerializer):
"need_delivering", "need_delivering",
"location", "location",
"locationName", "locationName",
"customer",
"owner",
"customer_and_owner_same",
"distance_covered",
"gov_number"
] ]
def validate_tex_passport(self, value): def validate_tex_passport(self, value):
@@ -157,7 +168,6 @@ class CreateEvaluationrequestSerializer(serializers.ModelSerializer):
{"tex_passport": "rate_type 'auto' bo'lganda tex_passport majburiy."} {"tex_passport": "rate_type 'auto' bo'lganda tex_passport majburiy."}
) )
# worked_hours va chassi FAQAT yuk avtomobil (truck_car) uchun majburiy
if object_type == "truck_car": if object_type == "truck_car":
if attrs.get("worked_hours") is None: if attrs.get("worked_hours") is None:
raise serializers.ValidationError( raise serializers.ValidationError(
@@ -183,7 +193,31 @@ class CreateEvaluationrequestSerializer(serializers.ModelSerializer):
if location_name: if location_name:
validated_data["location_name"] = str(location_name) validated_data["location_name"] = str(location_name)
validated_data["user"] = self.context["request"].user validated_data["user"] = self.context["request"].user
return super().create(validated_data)
instance = super().create(validated_data)
customer = validated_data.pop("customer", None)
owner = validated_data.pop("owner", None)
EvaluationRequestCustomerModel.objects.create(
evaluation_request=instance,
type=customer.get("type"),
jshshir=customer.get("jshshir")
)
if not instance.customer_and_owner_same:
EvaluationRequestOwnerModel.objects.create(
evaluation_request=instance,
type=owner.get("type"),
jshshir=owner.get("jshshir")
)
else:
EvaluationRequestOwnerModel.objects.create(
evaluation_request=instance,
type=customer.get("type"),
jshshir=customer.get("jshshir")
)
return instance
class ArchiveEvaluationrequestSerializer(serializers.Serializer): class ArchiveEvaluationrequestSerializer(serializers.Serializer):
id = serializers.IntegerField(required=True) id = serializers.IntegerField(required=True)

View File

@@ -0,0 +1,9 @@
from rest_framework import serializers
from core.apps.evaluation.models.request import EvaluationRequestOwnerModel
class EvaluationRequestOwnerSerializer(serializers.ModelSerializer):
class Meta:
model = EvaluationRequestOwnerModel
fields = ["id", "evaluation_request", "type", "jshshir"]

View File

@@ -0,0 +1,9 @@
from rest_framework import serializers
from core.apps.evaluation.models.request import EvaluationRequestCustomerModel
class EvaluationRequestCustomerSerializer(serializers.ModelSerializer):
class Meta:
model = EvaluationRequestCustomerModel
fields = ["id", "evaluation_request", "type", "jshshir"]

View File

@@ -1,90 +1,88 @@
from django.urls import include, path from django.urls import include, path
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from .views import ( from core.apps.evaluation import views
AdminEvaluationrequestView,
AutoEvaluationHistoryView,
AutoEvaluationView,
CustomerView,
DeterminedValueView,
DocumentCategoryView,
DocumentView,
EvaluationPurposeView,
EvaluationReportView,
EvaluationrequestView,
MovablePropertyEvaluationView,
OwnershipFormView,
PropertyOwnerView,
PropertyRightsView,
QuickEvaluationHistoryView,
QuickEvaluationView,
RealEstateEvaluationView,
ReferenceitemView,
ValuationDocumentView,
ValuationView,
VehicleView,
AutoEvaluationListAppraisersView,
AutoEvaluationSetAppraisersView,
AutoEvaluationRemoveAppraisersView,
DidoxCompanyInfoAPIView,
TechPassportAPIView,
EvaluationStatusChange,
CertificateView,
ArchiveQuickEvaluationView,
ArchiveEvaluationrequestView, GetArchivedEvaluationListAPIView, ArchivedEvaluation,
)
router = DefaultRouter() router = DefaultRouter()
router.register("document-category", DocumentCategoryView, basename="DocumentCategory") router.register("document-category", views.DocumentCategoryView, basename="DocumentCategory")
router.register("document", DocumentView, basename="Document") router.register("document", views.DocumentView, basename="Document")
router.register("auto-evaluation-history", AutoEvaluationHistoryView, basename="auto-evaluation-history") router.register("auto-evaluation-history", views.AutoEvaluationHistoryView, basename="auto-evaluation-history")
router.register("quick-evaluation-history", QuickEvaluationHistoryView, basename="quick-evaluation-history") router.register("quick-evaluation-history", views.QuickEvaluationHistoryView, basename="quick-evaluation-history")
router.register("determined-value", DeterminedValueView, basename="determined-value") router.register("determined-value", views.DeterminedValueView, basename="determined-value")
router.register("evaluation-purpose", EvaluationPurposeView, basename="evaluation-purpose") router.register("evaluation-purpose", views.EvaluationPurposeView, basename="evaluation-purpose")
router.register("property-rights", PropertyRightsView, basename="property-rights") router.register("property-rights", views.PropertyRightsView, basename="property-rights")
router.register("ownership-form", OwnershipFormView, basename="ownership-form") router.register("ownership-form", views.OwnershipFormView, basename="ownership-form")
router.register("evaluation-request", EvaluationrequestView, basename="evaluation-request") router.register("evaluation-request", views.EvaluationrequestView, basename="evaluation-request")
router.register("admin-evaluation-request", AdminEvaluationrequestView, basename="admin-evaluation-request") router.register("admin-evaluation-request", views.AdminEvaluationrequestView, basename="admin-evaluation-request")
router.register("reference-item", ReferenceitemView, basename="reference-item") router.register("reference-item", views.ReferenceitemView, basename="reference-item")
router.register("valuation-document", ValuationDocumentView, basename="valuation-document") router.register("valuation-document", views.ValuationDocumentView, basename="valuation-document")
router.register("evaluation-report", EvaluationReportView, basename="evaluation-report") router.register("evaluation-report", views.EvaluationReportView, basename="evaluation-report")
router.register("quick-evaluation", QuickEvaluationView, basename="quick-evaluation") router.register("quick-evaluation", views.QuickEvaluationView, basename="quick-evaluation")
router.register("movable-property-evaluation", MovablePropertyEvaluationView, basename="movable-property-evaluation") router.register("movable-property-evaluation", views.MovablePropertyEvaluationView, basename="movable-property-evaluation")
router.register("real-estate-evaluation", RealEstateEvaluationView, basename="real-estate-evaluation") router.register("real-estate-evaluation", views.RealEstateEvaluationView, basename="real-estate-evaluation")
router.register("auto-evaluation", AutoEvaluationView, basename="auto-evaluation") router.register("auto-evaluation", views.AutoEvaluationView, basename="auto-evaluation")
router.register("vehicle", VehicleView, basename="vehicle") router.register("vehicle", views.VehicleView, basename="vehicle")
router.register("valuation", ValuationView, basename="valuation") router.register("valuation", views.ValuationView, basename="valuation")
router.register("property-owner", PropertyOwnerView, basename="property-owner") router.register("property-owner", views.PropertyOwnerView, basename="property-owner")
router.register("customer", CustomerView, basename="customer") router.register("customer", views.CustomerView, basename="customer")
router.register("certificate", CertificateView, basename="certificate") router.register("certificate", views.CertificateView, basename="certificate")
urlpatterns = [ urlpatterns = [
path("", include(router.urls)), path("", include(router.urls)),
path("auto-evaluation/appraisers/", include(
path("didox/info/<int:tin>/", views.DidoxCompanyInfoAPIView.as_view()),
path("tech-passport/", views.TechPassportAPIView.as_view()),
# Quick Evaluation
path('quick-evaluation/', include(
[ [
path("<int:id>/list/", AutoEvaluationListAppraisersView.as_view(), name="auto-evaluation-list-appraisers"), path("admin/", views.AdminQuickEvalAPIView.as_view(), name="quick-evaluation"),
path("<int:id>/set/", AutoEvaluationSetAppraisersView.as_view(), name="auto-evaluation-set-appraisers"), path(
path("<int:id>/remove/", AutoEvaluationRemoveAppraisersView.as_view(), name="auto-evaluation-remove-appraisers"), 'archive/', include(
[
path("list/", views.QuickEvaluationArchivedListAPIView.as_view()),
path("<int:pk>/", views.QuickEvaluationArchiveAPIView.as_view()),
]
)
),
] ]
)), )),
path(
"didox/info/<int:tin>/",
DidoxCompanyInfoAPIView.as_view(),
name="didox-info"
),
path(
"tech-passport/",
TechPassportAPIView.as_view(),
name="tech-passport"
),
path("evaluation-request/<int:pk>/change-status/", EvaluationStatusChange.as_view(),
name="evaluation-change-status"),
path("archive/quick-evaluation/", ArchiveQuickEvaluationView.as_view(), name="quick-evaluation-archive"),
path("archive/evaluation-request/", ArchiveEvaluationrequestView.as_view(), name="evaluation-request-archive"),
path("archived-evaluvation/", GetArchivedEvaluationListAPIView.as_view(), # Auto Evaluation
name="archived-evaluation"), path("auto-evaluation/", include(
[
path("admin/", views.AdminEvaluationsAPIView.as_view(), name="admin-evaluations"),
path('archive/', include(
[
path('<int:pk>/', views.AutoEvaluationArchiveAPIView.as_view()),
path('list/', views.AutoEvaluationArchivedListAPIView.as_view())
]
)),
path('appraisers/', include(
[
path("<int:id>/list/", views.AutoEvaluationListAppraisersView.as_view()),
path("<int:id>/set/", views.AutoEvaluationSetAppraisersView.as_view()),
path("<int:id>/remove/", views.AutoEvaluationRemoveAppraisersView.as_view()),
]
))
]
)),
path("auto-evaluvation-change-status/<int:pk>", ArchivedEvaluation.as_view(), # Evaluation Request
name="archived-evaluation"), path("evaluation-request/", include(
[
path("<int:pk>/change-status/", views.EvaluationStatusChange.as_view()),
path(
'archive/', include(
[
path('list/', views.RequestEvaluationArchivedListAPIView.as_view()),
path('<int:pk>/', views.RequestEvaluationArchiveAPIView.as_view()),
]
)
)
]
)),
path("calculate_avg_cost/", views.AvgCostAPIView.as_view()),
] ]

View File

@@ -14,3 +14,4 @@ from .vehicle import * # noqa
from .didox import * # noqa from .didox import * # noqa
from .tech_passport import * # noqa from .tech_passport import * # noqa
from .certificate import * # noqa from .certificate import * # noqa
from .avg_cost import *

View File

@@ -3,6 +3,7 @@ from django.shortcuts import get_object_or_404
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.utils import extend_schema, OpenApiParameter from drf_spectacular.utils import extend_schema, OpenApiParameter
from rest_framework import generics
from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.generics import GenericAPIView, ListAPIView from rest_framework.generics import GenericAPIView, ListAPIView
from rest_framework.permissions import AllowAny, IsAuthenticated from rest_framework.permissions import AllowAny, IsAuthenticated
@@ -10,16 +11,11 @@ from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from core.apps.accounts.permissions import IsAdminRole
from core.apps.accounts.serializers.user import UserSerializer from core.apps.accounts.serializers.user import UserSerializer
from core.apps.evaluation.filters.auto import AutoevaluationFilter from core.apps.evaluation.filters.auto import AutoevaluationFilter
from core.apps.evaluation.models import AutoEvaluationModel from core.apps.evaluation.models import AutoEvaluationModel
from core.apps.evaluation.serializers.auto import ( from core.apps.evaluation.serializers import auto as serializers, AutoEvaluationModelSerializer
CreateAutoevaluationSerializer,
ListAutoevaluationSerializer,
RetrieveAutoevaluationSerializer,
AutoEvaluationAppraisersSerializer,
UpdateAutoevaluationSerializer
)
@extend_schema(tags=["AutoEvaluation"]) @extend_schema(tags=["AutoEvaluation"])
@@ -28,8 +24,8 @@ class AutoEvaluationView(BaseViewSetMixin, ModelViewSet):
"valuation", "valuation",
"valuation__customer", "valuation__customer",
"vehicle", "vehicle",
).all() ).filter(is_archived=False)
serializer_class = ListAutoevaluationSerializer serializer_class = serializers.ListAutoevaluationSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
@@ -67,18 +63,16 @@ class AutoEvaluationView(BaseViewSetMixin, ModelViewSet):
"created_at", "created_at",
"value_determined", "value_determined",
"rate_type", "rate_type",
"property_rights",
"form_ownership",
] ]
ordering = ["-created_at"] ordering = ["-created_at"]
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListAutoevaluationSerializer, "list": serializers.ListAutoevaluationSerializer,
"retrieve": RetrieveAutoevaluationSerializer, "retrieve": serializers.RetrieveAutoevaluationSerializer,
"create": CreateAutoevaluationSerializer, "create": serializers.CreateAutoevaluationSerializer,
"update": UpdateAutoevaluationSerializer, "update": serializers.UpdateAutoevaluationSerializer,
"partial_update": UpdateAutoevaluationSerializer, "partial_update": serializers.UpdateAutoevaluationSerializer,
} }
def serializer_context(self): def serializer_context(self):
@@ -89,7 +83,7 @@ class AutoEvaluationView(BaseViewSetMixin, ModelViewSet):
class AutoEvaluationSetAppraisersView(GenericAPIView): class AutoEvaluationSetAppraisersView(GenericAPIView):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
queryset = AutoEvaluationModel.objects.all() queryset = AutoEvaluationModel.objects.all()
serializer_class = AutoEvaluationAppraisersSerializer serializer_class = serializers.AutoEvaluationAppraisersSerializer
def post(self, request, id): def post(self, request, id):
try: try:
@@ -108,7 +102,7 @@ class AutoEvaluationSetAppraisersView(GenericAPIView):
class AutoEvaluationRemoveAppraisersView(GenericAPIView): class AutoEvaluationRemoveAppraisersView(GenericAPIView):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
queryset = AutoEvaluationModel.objects.all() queryset = AutoEvaluationModel.objects.all()
serializer_class = AutoEvaluationAppraisersSerializer serializer_class = serializers.AutoEvaluationAppraisersSerializer
def post(self, request, id): def post(self, request, id):
try: try:
@@ -158,18 +152,41 @@ class AutoEvaluationListAppraisersView(GenericAPIView):
@extend_schema(tags=["AutoEvaluation"]) @extend_schema(tags=["AutoEvaluation"])
class GetArchivedEvaluationListAPIView(ListAPIView): class AutoEvaluationArchivedListAPIView(ListAPIView):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
serializer_class = serializers.ListAutoevaluationSerializer
def get_queryset(self): def get_queryset(self):
return AutoEvaluationModel.objects.filter(is_archived=True) return AutoEvaluationModel.objects.filter(is_archived=True)
@extend_schema(tags=["AutoEvaluation"]) @extend_schema(tags=["AutoEvaluation"])
class ArchivedEvaluation(APIView): class AutoEvaluationArchiveAPIView(APIView):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
def post(self, request, pk): def post(self, request, pk):
auto_evaluation = get_object_or_404(AutoEvaluationModel, pk=pk) auto_evaluation = get_object_or_404(AutoEvaluationModel, pk=pk)
auto_evaluation.is_archived = request.data["is_archived"] auto_evaluation.is_archived = request.data["is_archived"]
auto_evaluation.save() auto_evaluation.save()
return Response({"success": True}, status=200) return Response(
{
"success": True,
"status": auto_evaluation.status,
"id": auto_evaluation.pk
},
status=200
)
@extend_schema(tags=["AutoEvaluation"])
class AdminEvaluationsAPIView(generics.GenericAPIView):
permission_classes = [IsAuthenticated, IsAdminRole]
queryset = AutoEvaluationModel.objects.all()
serializer_class = AutoEvaluationModel
def get(self, request):
auto_eval = AutoEvaluationModel.objects.filter(
created_by=self.request.user
).select_related('appraisers').distinct()
serializer = AutoEvaluationModelSerializer(auto_eval, many=True)
return Response(serializer.data)

View File

@@ -0,0 +1,37 @@
# rest framework
from rest_framework import generics
from rest_framework.response import Response
from rest_framework import permissions
# core apps
from core.apps.evaluation.serializers.auto.AvgCost import AvgCostSerializer
from core.services.grpc.auto import get_auto_avg_cost
class AvgCostAPIView(generics.GenericAPIView):
serializer_class = AvgCostSerializer
permission_classes = [permissions.IsAuthenticated]
def post(self, request):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
print(serializer.validated_data)
brand = serializer.validated_data['brand']
condition = serializer.validated_data['condition']
model = serializer.validated_data['model']
complication = serializer.validated_data['complication']
manufacture_date = serializer.validated_data['manufacture_date']
distance_covered = serializer.validated_data['distance_covered']
color = serializer.validated_data['color']
avg_cost = get_auto_avg_cost(
brand=brand,
condition=condition,
model=model,
complication=complication,
manufacture_date=manufacture_date,
distance_covered=str(distance_covered),
color=color
)
return Response(avg_cost, status=200)
return Response(serializer.errors, status=400)

View File

@@ -1,23 +1,30 @@
# django core
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
# swagger
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
from rest_framework.permissions import IsAuthenticated
# rest framework
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from core.apps.evaluation.models import CertificateModel from rest_framework.permissions import IsAuthenticated
from core.apps.evaluation.serializers.certificate import BaseCertificateSerializer
from rest_framework.filters import SearchFilter from rest_framework.filters import SearchFilter
from rest_framework.parsers import MultiPartParser, FormParser from rest_framework.parsers import MultiPartParser, FormParser
# local apps
from core.apps.evaluation.models import CertificateModel
from core.apps.evaluation.serializers.certificate import BaseCertificateSerializer, CreateCertificateSerializer
@extend_schema(tags=["Certificate"],request=BaseCertificateSerializer) @extend_schema(tags=["Certificate"],request=BaseCertificateSerializer)
class CertificateView(BaseViewSetMixin, ModelViewSet): class CertificateView(BaseViewSetMixin, ModelViewSet):
queryset = CertificateModel.objects.all() queryset = CertificateModel.objects.all()
serializer_class = BaseCertificateSerializer serializer_class = BaseCertificateSerializer
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
parser_classes = [MultiPartParser, FormParser] parser_classes = [MultiPartParser, FormParser]
filter_backends = [SearchFilter] filter_backends = [SearchFilter]
search_fields = ["title"] search_fields = ["title"]
pagination_class = None pagination_class = None
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = {
"create": CreateCertificateSerializer
}

View File

@@ -3,44 +3,33 @@ from drf_spectacular.utils import extend_schema
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet
# local apps
from core.apps.evaluation.models import CustomerModel, PropertyOwnerModel from core.apps.evaluation.models import CustomerModel, PropertyOwnerModel
from core.apps.evaluation.serializers.customer import ( from core.apps.evaluation.serializers import customer as serializers
CreateCustomerSerializer,
CreatePropertyOwnerSerializer,
ListCustomerSerializer,
ListPropertyOwnerSerializer,
RetrieveCustomerSerializer,
RetrievePropertyOwnerSerializer,
)
@extend_schema(tags=["Customer"]) @extend_schema(tags=["Customer"])
class CustomerView(BaseViewSetMixin, ReadOnlyModelViewSet): class CustomerView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = CustomerModel.objects.all() queryset = CustomerModel.objects.all()
serializer_class = ListCustomerSerializer serializer_class = serializers.ListCustomerSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListCustomerSerializer, "list": serializers.ListCustomerSerializer,
"retrieve": RetrieveCustomerSerializer, "retrieve": serializers.RetrieveCustomerSerializer,
"create": CreateCustomerSerializer, "create": serializers.CreateCustomerSerializer,
} }
@extend_schema(tags=["PropertyOwner"]) @extend_schema(tags=["PropertyOwner"])
class PropertyOwnerView(BaseViewSetMixin, ReadOnlyModelViewSet): class PropertyOwnerView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = PropertyOwnerModel.objects.all() queryset = PropertyOwnerModel.objects.all()
serializer_class = ListPropertyOwnerSerializer serializer_class = serializers.ListPropertyOwnerSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListPropertyOwnerSerializer, "list": serializers.ListPropertyOwnerSerializer,
"retrieve": RetrievePropertyOwnerSerializer, "retrieve": serializers.RetrievePropertyOwnerSerializer,
"create": CreatePropertyOwnerSerializer, "create": serializers.CreatePropertyOwnerSerializer,
} }
#test commit

View File

@@ -1,11 +1,13 @@
# rest framework
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import status from rest_framework import status
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import GenericAPIView from rest_framework.generics import GenericAPIView
# swagger
from drf_spectacular.utils import extend_schema, OpenApiParameter from drf_spectacular.utils import extend_schema, OpenApiParameter
# local apps
from core.services.didox import DidoxService from core.services.didox import DidoxService
@@ -38,7 +40,6 @@ class DidoxCompanyInfoAPIView(GenericAPIView):
{"detail": "TIN must be a valid integer"}, {"detail": "TIN must be a valid integer"},
status=status.HTTP_400_BAD_REQUEST status=status.HTTP_400_BAD_REQUEST
) )
data = DidoxService.get_company_info(tin) data = DidoxService.get_company_info(tin)
if not data: if not data:
@@ -47,14 +48,11 @@ class DidoxCompanyInfoAPIView(GenericAPIView):
status=status.HTTP_502_BAD_GATEWAY status=status.HTTP_502_BAD_GATEWAY
) )
# if both name and personalNum are null/empty -> 404
name = data.get("name") name = data.get("name")
personal_num = data.get("personalNum") personal_num = data.get("personalNum")
if not name and not personal_num: if not name and not personal_num:
return Response( return Response(
{"detail": "Company or person not found"}, {"detail": "Company or person not found"},
status=status.HTTP_404_NOT_FOUND status=status.HTTP_404_NOT_FOUND
) )
return Response(data, status=status.HTTP_200_OK) return Response(data, status=status.HTTP_200_OK)

View File

@@ -1,51 +1,51 @@
# django
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
# swagger
from drf_spectacular.utils import extend_schema, OpenApiParameter from drf_spectacular.utils import extend_schema, OpenApiParameter
# rest framework
from rest_framework.exceptions import NotFound, PermissionDenied from rest_framework.exceptions import NotFound, PermissionDenied
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.viewsets import ReadOnlyModelViewSet, ModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet, ModelViewSet
from rest_framework.parsers import FormParser, MultiPartParser from rest_framework.parsers import FormParser, MultiPartParser
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
# filters
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
from core.apps.evaluation.models import DocumentModel, ValuationDocumentModel, AutoEvaluationModel from core.apps.evaluation.models import DocumentModel, ValuationDocumentModel, AutoEvaluationModel
from core.apps.evaluation.serializers.document import ( from core.apps.evaluation.serializers import document as serializers
CreateDocumentSerializer,
CreateValuationdocumentSerializer,
ListDocumentSerializer,
ListValuationdocumentSerializer,
RetrieveDocumentSerializer,
RetrieveValuationdocumentSerializer,
)
@extend_schema(tags=["ValuationDocument"]) @extend_schema(tags=["ValuationDocument"])
class ValuationDocumentView(BaseViewSetMixin, ReadOnlyModelViewSet): class ValuationDocumentView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = ValuationDocumentModel.objects.all() queryset = ValuationDocumentModel.objects.all()
serializer_class = ListValuationdocumentSerializer serializer_class = serializers.ListValuationdocumentSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListValuationdocumentSerializer, "list": serializers.ListValuationdocumentSerializer,
"retrieve": RetrieveValuationdocumentSerializer, "retrieve": serializers.RetrieveValuationdocumentSerializer,
"create": CreateValuationdocumentSerializer, "create": serializers.CreateValuationdocumentSerializer,
} }
@extend_schema(tags=["Document"]) @extend_schema(tags=["Document"])
class DocumentView(BaseViewSetMixin, ModelViewSet): class DocumentView(BaseViewSetMixin, ModelViewSet):
queryset = DocumentModel.objects.all() queryset = DocumentModel.objects.all()
serializer_class = ListDocumentSerializer serializer_class = serializers.ListDocumentSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
parser_classes = [FormParser, MultiPartParser] parser_classes = [FormParser, MultiPartParser]
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListDocumentSerializer, "list": serializers.ListDocumentSerializer,
"retrieve": RetrieveDocumentSerializer, "retrieve": serializers.RetrieveDocumentSerializer,
"create": CreateDocumentSerializer, "create": serializers.CreateDocumentSerializer,
} }
@extend_schema( @extend_schema(
@@ -83,9 +83,9 @@ class DocumentView(BaseViewSetMixin, ModelViewSet):
documents = documents.filter(category_id=category_id) documents = documents.filter(category_id=category_id)
page = self.paginate_queryset(documents) page = self.paginate_queryset(documents)
if page is not None: if page is not None:
serializer = ListDocumentSerializer(page, many=True, context={"request": request}) serializer = serializers.ListDocumentSerializer(page, many=True, context={"request": request})
return self.get_paginated_response(serializer.data) return self.get_paginated_response(serializer.data)
serializer = ListDocumentSerializer(documents, many=True, context={"request": request}) serializer = serializers.ListDocumentSerializer(documents, many=True, context={"request": request})
return Response(serializer.data) return Response(serializer.data)
except AutoEvaluationModel.DoesNotExist: except AutoEvaluationModel.DoesNotExist:
raise NotFound("Auto evaluation not found") raise NotFound("Auto evaluation not found")

View File

@@ -1,8 +1,14 @@
# django core
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
# swagger
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
# rest framework
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet
# core apps
from core.apps.evaluation.models import DocumentcategoryModel from core.apps.evaluation.models import DocumentcategoryModel
from core.apps.evaluation.serializers.documentcategory import ( from core.apps.evaluation.serializers.documentcategory import (
ListDocumentcategorySerializer, ListDocumentcategorySerializer,

View File

@@ -1,24 +1,25 @@
# django
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
# django filters
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
# swagger
from drf_spectacular.utils import OpenApiParameter, extend_schema from drf_spectacular.utils import OpenApiParameter, extend_schema
# rest framework
from rest_framework.filters import OrderingFilter from rest_framework.filters import OrderingFilter
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet
# core apps
from core.apps.evaluation.filters.history import ( from core.apps.evaluation.filters.history import (
AutoevaluationhistoryFilter, AutoevaluationhistoryFilter,
QuickevaluationhistoryFilter, QuickevaluationhistoryFilter,
) )
from core.apps.evaluation.models import AutoevaluationhistoryModel, QuickevaluationhistoryModel from core.apps.evaluation.models import AutoevaluationhistoryModel, QuickevaluationhistoryModel
from core.apps.evaluation.serializers.history import ( from core.apps.evaluation.serializers import history as serializers
CreateAutoevaluationhistorySerializer,
CreateQuickevaluationhistorySerializer,
ListAutoevaluationhistorySerializer,
ListQuickevaluationhistorySerializer,
RetrieveAutoevaluationhistorySerializer,
RetrieveQuickevaluationhistorySerializer,
)
@extend_schema( @extend_schema(
@@ -31,13 +32,12 @@ from core.apps.evaluation.serializers.history import (
], ],
) )
class AutoEvaluationHistoryView(BaseViewSetMixin, ReadOnlyModelViewSet): class AutoEvaluationHistoryView(BaseViewSetMixin, ReadOnlyModelViewSet):
# select_related("auto_evaluation") faqat retrieve uchun — list uchun kerak emas
queryset = AutoevaluationhistoryModel.objects.only( queryset = AutoevaluationhistoryModel.objects.only(
"id", "auto_evaluation_id", "event_type", "id", "auto_evaluation_id", "event_type",
"actor_id", "actor_full_name", "actor_role", "actor_id", "actor_full_name", "actor_role",
"meta", "created_at", "meta", "created_at",
) )
serializer_class = ListAutoevaluationhistorySerializer serializer_class = serializers.ListAutoevaluationhistorySerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
pagination_class = None pagination_class = None
@@ -55,14 +55,13 @@ class AutoEvaluationHistoryView(BaseViewSetMixin, ReadOnlyModelViewSet):
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListAutoevaluationhistorySerializer, "list": serializers.ListAutoevaluationhistorySerializer,
"retrieve": RetrieveAutoevaluationhistorySerializer, "retrieve": serializers.RetrieveAutoevaluationhistorySerializer,
"create": CreateAutoevaluationhistorySerializer, "create": serializers.CreateAutoevaluationhistorySerializer,
} }
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset()) queryset = self.filter_queryset(self.get_queryset())
# Queryset bir marta evaluate qilinadi — COUNT uchun alohida query yo'q
results = list(queryset) results = list(queryset)
serializer = self.get_serializer(results, many=True) serializer = self.get_serializer(results, many=True)
return Response({ return Response({
@@ -88,7 +87,7 @@ class QuickEvaluationHistoryView(BaseViewSetMixin, ReadOnlyModelViewSet):
"actor_id", "actor_full_name", "actor_role", "actor_id", "actor_full_name", "actor_role",
"meta", "created_at", "meta", "created_at",
) )
serializer_class = ListQuickevaluationhistorySerializer serializer_class = serializers.ListQuickevaluationhistorySerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
pagination_class = None pagination_class = None
@@ -99,9 +98,9 @@ class QuickEvaluationHistoryView(BaseViewSetMixin, ReadOnlyModelViewSet):
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListQuickevaluationhistorySerializer, "list": serializers.ListQuickevaluationhistorySerializer,
"retrieve": RetrieveQuickevaluationhistorySerializer, "retrieve": serializers.RetrieveQuickevaluationhistorySerializer,
"create": CreateQuickevaluationhistorySerializer, "create": serializers.CreateQuickevaluationhistorySerializer,
} }
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):

View File

@@ -1,25 +1,27 @@
# django core
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
# swagger
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
# rest framework
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet
# core apps
from core.apps.evaluation.models import MovablePropertyEvaluationModel from core.apps.evaluation.models import MovablePropertyEvaluationModel
from core.apps.evaluation.serializers.movable import ( from core.apps.evaluation.serializers import movable as serializers
CreateMovablepropertyevaluationSerializer,
ListMovablepropertyevaluationSerializer,
RetrieveMovablepropertyevaluationSerializer,
)
@extend_schema(tags=["MovablePropertyEvaluation"]) @extend_schema(tags=["MovablePropertyEvaluation"])
class MovablePropertyEvaluationView(BaseViewSetMixin, ReadOnlyModelViewSet): class MovablePropertyEvaluationView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = MovablePropertyEvaluationModel.objects.all() queryset = MovablePropertyEvaluationModel.objects.all()
serializer_class = ListMovablepropertyevaluationSerializer serializer_class = serializers.ListMovablepropertyevaluationSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListMovablepropertyevaluationSerializer, "list": serializers.ListMovablepropertyevaluationSerializer,
"retrieve": RetrieveMovablepropertyevaluationSerializer, "retrieve": serializers.RetrieveMovablepropertyevaluationSerializer,
"create": CreateMovablepropertyevaluationSerializer, "create": serializers.CreateMovablepropertyevaluationSerializer,
} }

View File

@@ -1,23 +1,26 @@
# django
from django.shortcuts import get_object_or_404
# django core
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
# django filters
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.utils import extend_schema, OpenApiResponse # swagger
from drf_spectacular.utils import extend_schema
# rest framework
from rest_framework import status, generics
from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.generics import ListAPIView
from rest_framework.parsers import FormParser, MultiPartParser from rest_framework.parsers import FormParser, MultiPartParser
from rest_framework.permissions import AllowAny, IsAuthenticated from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.viewsets import ModelViewSet
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import status from rest_framework.views import APIView
from django.shortcuts import get_object_or_404 from rest_framework.viewsets import ModelViewSet
from core.apps.accounts.permissions import IsAdminRole
# core apps
from core.apps.evaluation.filters.quick import QuickevaluationFilter from core.apps.evaluation.filters.quick import QuickevaluationFilter
from core.apps.evaluation.models import QuickEvaluationModel from core.apps.evaluation.models import QuickEvaluationModel
from core.apps.evaluation.serializers.quick import ( from core.apps.evaluation.serializers import quick as serializers, QuickEvaluationModelSerializer
CreateQuickevaluationSerializer,
ListQuickevaluationSerializer,
RetrieveQuickevaluationSerializer,
ArchiveQuickevaluationSerializer,
)
@extend_schema(tags=["QuickEvaluation"]) @extend_schema(tags=["QuickEvaluation"])
@@ -26,7 +29,7 @@ class QuickEvaluationView(BaseViewSetMixin, ModelViewSet):
"created_by", "brand", "marka", "color", "fuel_type", "created_by", "brand", "marka", "color", "fuel_type",
"body_type", "state_car", "car_position", "body_type", "state_car", "car_position",
).filter(is_archive=False) ).filter(is_archive=False)
serializer_class = ListQuickevaluationSerializer serializer_class = serializers.ListQuickevaluationSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
parser_classes = [MultiPartParser, FormParser] parser_classes = [MultiPartParser, FormParser]
@@ -51,80 +54,48 @@ class QuickEvaluationView(BaseViewSetMixin, ModelViewSet):
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListQuickevaluationSerializer, "list": serializers.ListQuickevaluationSerializer,
"retrieve": RetrieveQuickevaluationSerializer, "retrieve": serializers.RetrieveQuickevaluationSerializer,
"create": CreateQuickevaluationSerializer, "create": serializers.CreateQuickevaluationSerializer,
} }
@extend_schema(tags=["QuickEvaluation"]) @extend_schema(tags=["QuickEvaluation"])
class ArchiveQuickEvaluationView(GenericAPIView): class QuickEvaluationArchiveAPIView(APIView):
def post(self, request, pk):
instance = get_object_or_404(QuickEvaluationModel, pk=pk)
is_archived = request.data.get("is_archived")
if is_archived is None:
return Response(
{"error": "Поле 'is_archived' обязательно"},
status=status.HTTP_400_BAD_REQUEST
)
instance.is_archive = is_archived
instance.save()
return Response({"success": True}, status=200)
@extend_schema(tags=["QuickEvaluation"])
class QuickEvaluationArchivedListAPIView(ListAPIView):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
serializer_class = serializers.ListQuickevaluationSerializer
def get_serializer_class(self): def get_queryset(self):
if self.request.method == "GET": return QuickEvaluationModel.objects.filter(is_archive=True)
return ListQuickevaluationSerializer
return ArchiveQuickevaluationSerializer
@extend_schema(
tags=["QuickEvaluation"],
summary="Get archived quick evaluations list",
description="""
Returns only archived quick evaluations.
This endpoint works like quick-evaluation/, @extend_schema(tags=["QuickEvaluation"])
but only records with is_archive=True are returned. class AdminQuickEvalAPIView(generics.GenericAPIView):
""", permission_classes = [IsAuthenticated, IsAdminRole]
responses={200: ListQuickevaluationSerializer(many=True)}, queryset = QuickEvaluationModel.objects.all()
) serializer_class = QuickEvaluationModelSerializer
def get(self, request, *args, **kwargs):
queryset = QuickEvaluationModel.objects.filter(
is_archive=True
).order_by("-created_at")
serializer = self.get_serializer(queryset, many=True) def get(self, request):
quick_eval = QuickEvaluationModel.objects.filter(
created_by=self.request.user
).select_related('created_by').distinct()
serializer = QuickEvaluationModelSerializer(quick_eval, many=True)
return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.data)
@extend_schema(
tags=["QuickEvaluation"],
summary="Archive or unarchive quick evaluation",
description="""
Update archive status for quick evaluation.
- is_archive=true → archive
- is_archive=false → remove from archive
""",
request=ArchiveQuickevaluationSerializer,
responses={
200: OpenApiResponse(
description="Archive status updated successfully"
),
400: OpenApiResponse(
description="Validation error"
),
404: OpenApiResponse(
description="Quick evaluation not found"
),
},
)
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
validated_data = serializer.validated_data
obj = get_object_or_404(
QuickEvaluationModel,
id=validated_data["id"]
)
obj.is_archive = validated_data["is_archive"]
obj.save(update_fields=["is_archive"])
return Response(
{
"success": True,
"message": "Archive status updated successfully"
},
status=status.HTTP_200_OK
)

View File

@@ -1,25 +1,27 @@
# django core
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
# swagger
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
# rest framework
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet
# core
from core.apps.evaluation.models import RealEstateEvaluationModel from core.apps.evaluation.models import RealEstateEvaluationModel
from core.apps.evaluation.serializers.real_estate import ( from core.apps.evaluation.serializers import real_estate as serializers
CreateRealestateevaluationSerializer,
ListRealestateevaluationSerializer,
RetrieveRealestateevaluationSerializer,
)
@extend_schema(tags=["RealEstateEvaluation"]) @extend_schema(tags=["RealEstateEvaluation"])
class RealEstateEvaluationView(BaseViewSetMixin, ReadOnlyModelViewSet): class RealEstateEvaluationView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = RealEstateEvaluationModel.objects.all() queryset = RealEstateEvaluationModel.objects.all()
serializer_class = ListRealestateevaluationSerializer serializer_class = serializers.ListRealestateevaluationSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListRealestateevaluationSerializer, "list": serializers.ListRealestateevaluationSerializer,
"retrieve": RetrieveRealestateevaluationSerializer, "retrieve": serializers.RetrieveRealestateevaluationSerializer,
"create": CreateRealestateevaluationSerializer, "create": serializers.CreateRealestateevaluationSerializer,
} }

View File

@@ -1,20 +1,21 @@
# django core
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
# django filters
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
# swagger
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
# rest framework
from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet
# core apps
from core.apps.evaluation.filters.reference import ReferenceitemFilter from core.apps.evaluation.filters.reference import ReferenceitemFilter
from core.apps.evaluation.models import ReferenceitemModel from core.apps.evaluation.models import ReferenceitemModel
from core.apps.evaluation.serializers.reference import ( from core.apps.evaluation.serializers import reference as serializers
CreateReferenceitemSerializer,
ListReferenceitemSerializer,
RetrieveReferenceitemSerializer,
EvaluationPurposeSerializer,
DeterminedValueSerializer,
LabelValueSerializer,
)
@extend_schema(tags=["EvaluationPurpose"]) @extend_schema(tags=["EvaluationPurpose"])
@@ -22,10 +23,9 @@ class EvaluationPurposeView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = ReferenceitemModel.objects.filter( queryset = ReferenceitemModel.objects.filter(
type="evaluation_purpose", is_active=True type="evaluation_purpose", is_active=True
).order_by("order", "name") ).order_by("order", "name")
serializer_class = EvaluationPurposeSerializer serializer_class = serializers.EvaluationPurposeSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
pagination_class = None pagination_class = None
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
search_fields = ["name"] search_fields = ["name"]
ordering_fields = ["name", "order"] ordering_fields = ["name", "order"]
@@ -37,10 +37,9 @@ class DeterminedValueView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = ReferenceitemModel.objects.filter( queryset = ReferenceitemModel.objects.filter(
type="determined_value", is_active=True type="determined_value", is_active=True
).order_by("order", "name") ).order_by("order", "name")
serializer_class = DeterminedValueSerializer serializer_class = serializers.DeterminedValueSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
pagination_class = None pagination_class = None
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
search_fields = ["name"] search_fields = ["name"]
ordering_fields = ["name", "order"] ordering_fields = ["name", "order"]
@@ -52,10 +51,9 @@ class PropertyRightsView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = ReferenceitemModel.objects.filter( queryset = ReferenceitemModel.objects.filter(
type="property_rights", is_active=True type="property_rights", is_active=True
).order_by("order", "name") ).order_by("order", "name")
serializer_class = LabelValueSerializer serializer_class = serializers.LabelValueSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
pagination_class = None pagination_class = None
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
search_fields = ["name"] search_fields = ["name"]
ordering_fields = ["name", "order"] ordering_fields = ["name", "order"]
@@ -67,10 +65,9 @@ class OwnershipFormView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = ReferenceitemModel.objects.filter( queryset = ReferenceitemModel.objects.filter(
type="ownership_form", is_active=True type="ownership_form", is_active=True
).order_by("order", "name") ).order_by("order", "name")
serializer_class = LabelValueSerializer serializer_class = serializers.LabelValueSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
pagination_class = None pagination_class = None
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
search_fields = ["name"] search_fields = ["name"]
ordering_fields = ["name", "order"] ordering_fields = ["name", "order"]
@@ -80,18 +77,16 @@ class OwnershipFormView(BaseViewSetMixin, ReadOnlyModelViewSet):
@extend_schema(tags=["ReferenceItem"]) @extend_schema(tags=["ReferenceItem"])
class ReferenceitemView(BaseViewSetMixin, ReadOnlyModelViewSet): class ReferenceitemView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = ReferenceitemModel.objects.select_related("parent").filter(is_active=True) queryset = ReferenceitemModel.objects.select_related("parent").filter(is_active=True)
serializer_class = ListReferenceitemSerializer serializer_class = serializers.ListReferenceitemSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_class = ReferenceitemFilter filterset_class = ReferenceitemFilter
search_fields = ["name"] search_fields = ["name"]
ordering_fields = ["name", "order", "type"] ordering_fields = ["name", "order", "type"]
ordering = ["order", "name"] ordering = ["order", "name"]
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListReferenceitemSerializer, "list": serializers.ListReferenceitemSerializer,
"retrieve": RetrieveReferenceitemSerializer, "retrieve": serializers.RetrieveReferenceitemSerializer,
"create": CreateReferenceitemSerializer, "create": serializers.CreateReferenceitemSerializer,
} }

View File

@@ -1,25 +1,26 @@
# django core
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
# swagger
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
# rest framework
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet
# core apps
from core.apps.evaluation.models import EvaluationReportModel from core.apps.evaluation.models import EvaluationReportModel
from core.apps.evaluation.serializers.report import ( from core.apps.evaluation.serializers import report as serializers
CreateEvaluationreportSerializer,
ListEvaluationreportSerializer,
RetrieveEvaluationreportSerializer,
)
@extend_schema(tags=["EvaluationReport"]) @extend_schema(tags=["EvaluationReport"])
class EvaluationReportView(BaseViewSetMixin, ReadOnlyModelViewSet): class EvaluationReportView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = EvaluationReportModel.objects.all() queryset = EvaluationReportModel.objects.all()
serializer_class = ListEvaluationreportSerializer serializer_class = serializers.ListEvaluationreportSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListEvaluationreportSerializer, "list": serializers.ListEvaluationreportSerializer,
"retrieve": RetrieveEvaluationreportSerializer, "retrieve": serializers.RetrieveEvaluationreportSerializer,
"create": CreateEvaluationreportSerializer, "create": serializers.CreateEvaluationreportSerializer,
} }

View File

@@ -1,42 +1,33 @@
# django
from django.db.models.base import transaction
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
# django core
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.utils import extend_schema
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
# django filters
from django_filters.rest_framework import DjangoFilterBackend
# swagger
from drf_spectacular.utils import extend_schema
# rest framework
from rest_framework import status, filters, generics, permissions, views, viewsets
from rest_framework.response import Response
# core apps
from core.apps.accounts.choices import RoleChoice
from core.apps.evaluation.choices.request import RequestStatus
from core.apps.evaluation.filters.request import EvaluationrequestFilter from core.apps.evaluation.filters.request import EvaluationrequestFilter
from core.apps.evaluation.models import EvaluationrequestModel from core.apps.evaluation.models import EvaluationrequestModel
from core.apps.evaluation.serializers.request import ( from core.apps.evaluation.serializers import request as serializers
CreateEvaluationrequestSerializer,
ListEvaluationrequestSerializer,
RetrieveEvaluationrequestSerializer,
ArchiveEvaluationrequestSerializer,
)
from core.apps.evaluation.choices.request import RequestStatus
from rest_framework.generics import GenericAPIView
from drf_spectacular.utils import OpenApiResponse
# class RequestPagination(PageNumberPagination):
# page_size = 20
# page_size_query_param = "limit"
# max_page_size = 100
@extend_schema(tags=["EvaluationRequest"]) @extend_schema(tags=["EvaluationRequest"])
class EvaluationrequestView(BaseViewSetMixin, ModelViewSet): class EvaluationrequestView(BaseViewSetMixin, viewsets.ModelViewSet):
serializer_class = ListEvaluationrequestSerializer serializer_class = serializers.ListEvaluationrequestSerializer
permission_classes = [IsAuthenticated] permission_classes = [permissions.IsAuthenticated]
# pagination_class = RequestPagination filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_class = EvaluationrequestFilter filterset_class = EvaluationrequestFilter
search_fields = [ search_fields = [
"customer_inn_number", "customer_inn_number",
@@ -71,9 +62,9 @@ class EvaluationrequestView(BaseViewSetMixin, ModelViewSet):
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListEvaluationrequestSerializer, "list": serializers.ListEvaluationrequestSerializer,
"retrieve": RetrieveEvaluationrequestSerializer, "retrieve": serializers.RetrieveEvaluationrequestSerializer,
"create": CreateEvaluationrequestSerializer, "create": serializers.CreateEvaluationrequestSerializer,
} }
def serializer_context(self): def serializer_context(self):
@@ -81,18 +72,15 @@ class EvaluationrequestView(BaseViewSetMixin, ModelViewSet):
def get_queryset(self): def get_queryset(self):
return EvaluationrequestModel.objects.filter( return EvaluationrequestModel.objects.filter(
user=self.request.user user=self.request.user, is_archive=False
).order_by("-created_at") ).order_by("-created_at")
@extend_schema(tags=["EvaluationRequest"]) @extend_schema(tags=["EvaluationRequest"])
class AdminEvaluationrequestView(BaseViewSetMixin, ModelViewSet): class AdminEvaluationrequestView(BaseViewSetMixin, viewsets.ModelViewSet):
serializer_class = ListEvaluationrequestSerializer serializer_class = serializers.ListEvaluationrequestSerializer
permission_classes = [IsAuthenticated] permission_classes = [permissions.IsAuthenticated]
# pagination_class = RequestPagination filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_class = EvaluationrequestFilter filterset_class = EvaluationrequestFilter
search_fields = [ search_fields = [
"customer_inn_number", "customer_inn_number",
@@ -127,29 +115,29 @@ class AdminEvaluationrequestView(BaseViewSetMixin, ModelViewSet):
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListEvaluationrequestSerializer, "list": serializers.ListEvaluationrequestSerializer,
"retrieve": RetrieveEvaluationrequestSerializer, "retrieve": serializers.RetrieveEvaluationrequestSerializer,
"create": CreateEvaluationrequestSerializer, "create": serializers.CreateEvaluationrequestSerializer,
} }
def get_queryset(self): def get_queryset(self):
return EvaluationrequestModel.objects.select_related("value_determined", "rate_goal", "property_rights", "form_ownership", "user").order_by("-created_at") return EvaluationrequestModel.objects.\
select_related("value_determined","rate_goal","property_rights","form_ownership","user")\
.order_by("-created_at")
def serializer_context(self): def serializer_context(self):
return self.serializer_class(context={"request": self.request}) return self.serializer_class(context={"request": self.request})
@extend_schema(tags=["EvaluationRequest"]) @extend_schema(tags=["EvaluationRequest"])
class EvaluationStatusChange(APIView): class EvaluationStatusChange(views.APIView):
permission_classes = [IsAuthenticated] permission_classes = [permissions.IsAuthenticated]
def post(self, request, pk): def post(self, request, pk):
if request.user.role not in [RoleChoice.ADMIN, RoleChoice.SUPERUSER]: if request.user.role not in [RoleChoice.ADMIN, RoleChoice.SUPERUSER]:
return Response({'detail': 'Forbidden'}, status=status.HTTP_403_FORBIDDEN) return Response({'detail': 'Forbidden'}, status=status.HTTP_403_FORBIDDEN)
evaluation = get_object_or_404(EvaluationrequestModel, pk=pk) evaluation = get_object_or_404(EvaluationrequestModel, pk=pk)
status_value = request.data.get('status') status_value = request.data.get('status')
if not status_value: if not status_value:
return Response({'detail': 'Status is required'}, status=status.HTTP_400_BAD_REQUEST) return Response({'detail': 'Status is required'}, status=status.HTTP_400_BAD_REQUEST)
@@ -176,75 +164,30 @@ class EvaluationStatusChange(APIView):
'id': evaluation.pk 'id': evaluation.pk
}) })
@extend_schema(tags=["EvaluationRequest"]) @extend_schema(tags=["EvaluationRequest"])
class ArchiveEvaluationrequestView(GenericAPIView): class RequestEvaluationArchivedListAPIView(generics.ListAPIView):
permission_classes = [IsAuthenticated] permission_classes = [permissions.IsAuthenticated]
serializer_class = serializers.ListEvaluationrequestSerializer
def get_serializer_class(self): def get_queryset(self):
if self.request.method == "GET": return EvaluationrequestModel.objects.filter(is_archive=True)
return ListEvaluationrequestSerializer
return ArchiveEvaluationrequestSerializer
@extend_schema(
tags=["EvaluationRequest"],
summary="Get archived evaluation requests list",
description="""
Returns only archived evaluation requests.
This endpoint works like evaluation-request/, @extend_schema(tags=["EvaluationRequest"])
but only records with is_archive=True are returned. class RequestEvaluationArchiveAPIView(views.APIView):
""", permission_classes = [permissions.IsAuthenticated]
responses={200: ListEvaluationrequestSerializer(many=True)},
)
def get(self, request, *args, **kwargs):
queryset = EvaluationrequestModel.objects.filter(
is_archive=True
).order_by("-created_at")
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
@extend_schema(
tags=["EvaluationRequest"],
summary="Archive or unarchive evaluation request",
description="""
Update archive status for evaluation request.
- is_archive=true → archive
- is_archive=false → remove from archive
""",
request=ArchiveEvaluationrequestSerializer,
responses={
200: OpenApiResponse(
description="Archive status updated successfully"
),
400: OpenApiResponse(
description="Validation error"
),
404: OpenApiResponse(
description="Evaluation request not found"
),
},
)
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
validated_data = serializer.validated_data
obj = get_object_or_404(
EvaluationrequestModel,
id=validated_data["id"]
)
obj.is_archive = validated_data["is_archive"]
obj.save(update_fields=["is_archive"])
@transaction.atomic
def post(self, request, pk):
req_evaluation = get_object_or_404(EvaluationrequestModel, pk=pk)
req_evaluation.is_archive = request.data["is_archived"]
req_evaluation.save()
return Response( return Response(
{ {
"success": True, "success": True,
"message": "Archive status updated successfully" "status": req_evaluation.status,
"id": req_evaluation.pk
}, },
status=status.HTTP_200_OK status=status.HTTP_200_OK
) )

View File

@@ -1,15 +1,15 @@
# rest framework
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import status from rest_framework import status
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import GenericAPIView from rest_framework.generics import GenericAPIView
from drf_spectacular.utils import ( # swagger
extend_schema, from drf_spectacular.utils import extend_schema
OpenApiExample,
)
# core apps
from core.services.tech_passport import TechPassportService from core.services.tech_passport import TechPassportService
from ..serializers import TechPassportSerializer from core.apps.evaluation.serializers import TechPassportSerializer
class TechPassportAPIView(GenericAPIView): class TechPassportAPIView(GenericAPIView):
@@ -18,12 +18,6 @@ class TechPassportAPIView(GenericAPIView):
@extend_schema( @extend_schema(
tags=["Tech Passport"], tags=["Tech Passport"],
summary="Get vehicle information by technical passport",
description=(
"This endpoint retrieves vehicle information using "
"autonumber, technical passport number, and technical passport series "
"via Gross Insurance API integration."
),
request=TechPassportSerializer, request=TechPassportSerializer,
responses={ responses={
200: dict, 200: dict,
@@ -45,14 +39,12 @@ class TechPassportAPIView(GenericAPIView):
response_data = result["data"] response_data = result["data"]
status_code = result["status_code"] status_code = result["status_code"]
# success bolsa faqat data ichidagi data qaytariladi
if status_code == 200: if status_code == 200:
return Response( return Response(
response_data.get("data", {}), response_data.get("data", {}),
status=status.HTTP_200_OK status=status.HTTP_200_OK
) )
# error bolsa original response qaytariladi
return Response( return Response(
response_data, response_data,
status=status_code status=status_code

View File

@@ -1,25 +1,27 @@
# django core
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
# swagger
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
# rest framework
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet
# core apps
from core.apps.evaluation.models import ValuationModel from core.apps.evaluation.models import ValuationModel
from core.apps.evaluation.serializers.valuation import ( from core.apps.evaluation.serializers import valuation as serializers
CreateValuationSerializer,
ListValuationSerializer,
RetrieveValuationSerializer,
)
@extend_schema(tags=["Valuation"]) @extend_schema(tags=["Valuation"])
class ValuationView(BaseViewSetMixin, ReadOnlyModelViewSet): class ValuationView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = ValuationModel.objects.all() queryset = ValuationModel.objects.all()
serializer_class = ListValuationSerializer serializer_class = serializers.ListValuationSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListValuationSerializer, "list": serializers.ListValuationSerializer,
"retrieve": RetrieveValuationSerializer, "retrieve": serializers.RetrieveValuationSerializer,
"create": CreateValuationSerializer, "create": serializers.CreateValuationSerializer,
} }

View File

@@ -1,14 +1,16 @@
# django core
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
# swagger
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
# rest framework
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet
# core apps
from core.apps.evaluation.models import VehicleModel from core.apps.evaluation.models import VehicleModel
from core.apps.evaluation.serializers.vehicle import ( from core.apps.evaluation.serializers import vehicle as serialziers
CreateVehicleSerializer,
ListVehicleSerializer,
RetrieveVehicleSerializer,
)
@extend_schema(tags=["Vehicle"]) @extend_schema(tags=["Vehicle"])
@@ -16,12 +18,12 @@ class VehicleView(BaseViewSetMixin, ReadOnlyModelViewSet):
queryset = VehicleModel.objects.select_related( queryset = VehicleModel.objects.select_related(
"brand", "model", "color", "fuel_type", "body_type", "position", "brand", "model", "color", "fuel_type", "body_type", "position",
).all() ).all()
serializer_class = ListVehicleSerializer serializer_class = serialziers.ListVehicleSerializer
permission_classes = [AllowAny] permission_classes = [AllowAny]
action_permission_classes = {} action_permission_classes = {}
action_serializer_class = { action_serializer_class = {
"list": ListVehicleSerializer, "list": serialziers.ListVehicleSerializer,
"retrieve": RetrieveVehicleSerializer, "retrieve": serialziers.RetrieveVehicleSerializer,
"create": CreateVehicleSerializer, "create": serialziers.CreateVehicleSerializer,
} }

View File

@@ -0,0 +1,4 @@
from .column import *
from .comment import *
from .task import *
from .label import *

View File

@@ -0,0 +1,7 @@
from django.contrib import admin
from core.apps.tasks.models import Column
@admin.register(Column)
class ColumnAdmin(admin.ModelAdmin):
list_display = ('name',)

View File

@@ -0,0 +1,7 @@
from django.contrib import admin
from core.apps.tasks.models import Comment
@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
list_display = ('created_by', 'type')

View File

@@ -0,0 +1,7 @@
from django.contrib import admin
from core.apps.tasks.models import Label
@admin.register(Label)
class LabelAdmin(admin.ModelAdmin):
list_display = ('name',)

View File

@@ -0,0 +1,7 @@
from django.contrib import admin
from core.apps.tasks.models import Task
@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
list_display = ('name', 'created_by', 'priority')

8
core/apps/tasks/apps.py Normal file
View File

@@ -0,0 +1,8 @@
from django.apps import AppConfig
class TasksConfig(AppConfig):
name = "core.apps.tasks"
def ready(self):
from core.apps.tasks import admin

View File

@@ -0,0 +1,6 @@
from django.db import models
class MessageChoice(models.TextChoices):
FILE = "file", "File"
TEXT = "text", "Text"

View File

@@ -0,0 +1,7 @@
from django.db import models
class PriorityChoice(models.TextChoices):
LOW = "low", "Low"
MEDIUM = "medium", "Medium"
HIGH = "high", "High"

View File

@@ -0,0 +1,77 @@
# Generated by Django 5.2.7 on 2026-04-29 13:18
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Column',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('name', models.CharField(max_length=255)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Label',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('name', models.CharField(max_length=255)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Task',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('name', models.CharField(max_length=255)),
('description', models.TextField(blank=True)),
('priority', models.CharField(choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High')], max_length=255)),
('from_date', models.DateField(blank=True, null=True)),
('to_date', models.DateField(blank=True, null=True)),
('assignees', models.ManyToManyField(related_name='assigned_tasks', to=settings.AUTH_USER_MODEL)),
('column', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tasks', to='tasks.column')),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='created_tasks', to=settings.AUTH_USER_MODEL)),
('labels', models.ManyToManyField(related_name='tasks', to='tasks.label')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Comment',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('message', models.TextField()),
('file', models.FileField(blank=True, null=True, upload_to='comments/')),
('type', models.CharField(choices=[('file', 'File'), ('text', 'Text')], max_length=255)),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='created_comments', to=settings.AUTH_USER_MODEL)),
('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='tasks.task')),
],
options={
'abstract': False,
},
),
]

View File

@@ -0,0 +1,21 @@
# Generated by Django 5.2.7 on 2026-04-29 13:20
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tasks', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AlterField(
model_name='comment',
name='created_by',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to=settings.AUTH_USER_MODEL),
),
]

View File

View File

@@ -0,0 +1,4 @@
from .column import *
from .comment import *
from .task import *
from .label import *

View File

@@ -0,0 +1,10 @@
from django.db import models
from django_core.models import AbstractBaseModel
class Column(AbstractBaseModel):
name = models.CharField(max_length=255)
def __str__(self):
return self.name

View File

@@ -0,0 +1,16 @@
from django.db import models
from django_core.models import AbstractBaseModel
from core.apps.tasks.choices.comment import MessageChoice
class Comment(AbstractBaseModel):
task = models.ForeignKey('tasks.Task', on_delete=models.CASCADE, related_name='comments')
message = models.TextField()
file = models.FileField(upload_to='comments/', blank=True, null=True)
type = models.CharField(max_length=255, choices=MessageChoice.choices)
created_by = models.ForeignKey('accounts.User', on_delete=models.CASCADE, related_name='comments')
def __str__(self):
return f"{self.content} created by {self.created_by}"

View File

@@ -0,0 +1,10 @@
from django.db import models
from django_core.models import AbstractBaseModel
class Label(AbstractBaseModel):
name = models.CharField(max_length=255)
def __str__(self):
return self.name

View File

@@ -0,0 +1,20 @@
from django.db import models
from django_core.models import AbstractBaseModel
from core.apps.tasks.choices.task import PriorityChoice
class Task(AbstractBaseModel):
column = models.ForeignKey('tasks.Column', on_delete=models.CASCADE, related_name='tasks')
name = models.CharField(max_length=255)
description = models.TextField(blank=True)
priority = models.CharField(max_length=255, choices=PriorityChoice.choices)
from_date = models.DateField(null=True, blank=True)
to_date = models.DateField(null=True, blank=True)
labels = models.ManyToManyField('tasks.Label', related_name='tasks')
assignees = models.ManyToManyField('accounts.User', related_name='assigned_tasks')
created_by = models.ForeignKey('accounts.User', on_delete=models.CASCADE, related_name='created_tasks')
def __str__(self):
return f"{self.name} created by {self.created_by}"

View File

@@ -0,0 +1,22 @@
from rest_framework import serializers
from core.apps.tasks.serializers.comment import CommentSerializer
from core.apps.tasks.serializers.task import TaskSerializer
from core.apps.tasks.models import Column, Task
class BoardTaskSerializer(TaskSerializer):
comments = CommentSerializer(many=True, read_only=True)
class Meta(TaskSerializer.Meta):
TaskSerializer.Meta.fields += ['comments']
class BoardSerializer(serializers.ModelSerializer):
tasks = BoardTaskSerializer(many=True, read_only=True)
class Meta:
model = Column
fields = [
'id', 'name', 'tasks',
]

View File

@@ -0,0 +1,11 @@
from rest_framework import serializers
from core.apps.tasks.models.column import Column
class ColumnSerializer(serializers.ModelSerializer):
class Meta:
model = Column
fields = [
'id', 'name'
]

View File

@@ -0,0 +1,44 @@
from django.db import transaction
from rest_framework import serializers
from core.apps.tasks.models.comment import Comment
from core.apps.tasks.models.task import Task
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = [
'id', 'message', 'file', 'type', 'created_by'
]
def get_created_by(self, obj):
request = self.context.get('request')
return {
"id": obj.created_by.id,
"first_name": obj.created_by.first_name,
"last_name": obj.created_by.last_name,
"avatar": request.build_absolute_uri(obj.created_by.avatar.url) if obj.created_by.avatar else None
}
class CommentCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = [
'id', 'message', 'file', 'type', 'task'
]
def validate(self, data):
task = Task.objects.filter(id=data['task']).first()
if not task:
raise serializers.ValidationError("Task not found")
data['task'] = task
return data
def create(self, validated_data):
with transaction.atomic():
task = validated_data.pop('task')
comment = Comment.objects.create(task=task, created_by=self.context['request'].user, **validated_data)
return comment

View File

@@ -0,0 +1,11 @@
from rest_framework import serializers
from core.apps.tasks.models.label import Label
class LabelSerializer(serializers.ModelSerializer):
class Meta:
model = Label
fields = [
'id', 'name'
]

View File

@@ -0,0 +1,52 @@
from rest_framework import serializers
from core.apps.tasks.models.task import Task
from core.apps.accounts.serializers.user import ShortUserSerializer
from core.apps.tasks.serializers.label import LabelSerializer
class TaskSerializer(serializers.ModelSerializer):
labels = LabelSerializer(many=True)
assignees = serializers.SerializerMethodField(method_name='get_assignees')
created_by = serializers.SerializerMethodField(method_name='get_created_by')
class Meta:
model = Task
fields = [
'id',
'column',
'name',
'description',
'priority',
'from_date',
'to_date',
'labels',
'assignees',
'created_by'
]
def get_assignees(self, obj):
return ShortUserSerializer(obj.assignees.all(), many=True, context={"request": self.context['request']}).data
def get_created_by(self, obj):
return ShortUserSerializer(obj.created_by, context={"request": self.context['request']}).data
class TaskCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = [
'id',
'column',
'name',
'description',
'priority',
'from_date',
'to_date',
'labels',
'assignees',
]
def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user
return super().create(validated_data)

34
core/apps/tasks/urls.py Normal file
View File

@@ -0,0 +1,34 @@
from django.urls import path, include
from core.apps.tasks.views import task, column, comment, label, board
urlpatterns = [
path('column/', include(
[
path('list/', column.ColumnListApiView.as_view()),
path('create/', column.ColumnCreateApiView.as_view()),
path('<int:id>/update/', column.ColumnUpdateApiView.as_view()),
path('<int:id>/delete/', column.ColumnDeleteApiView.as_view())
]
)),
path('label/', include(
[
path('', label.LabelListCreateApiView.as_view()),
path('<int:id>/', label.LabelRetrieveUpdateDestroyApiView.as_view()),
]
)),
path('task/', include(
[
path('list/', task.TaskListView.as_view()),
path('<int:id>/', task.TaskDetailView.as_view()),
path('create/', task.TaskCreateView.as_view()),
]
)),
path('comment/', include(
[
path('', comment.CommentListCreateAPIView.as_view()),
path('<int:pk>/', comment.CommentDetailAPIView.as_view()),
]
)),
path('board/', board.BoardListView.as_view()),
]

View File

@@ -0,0 +1,13 @@
from rest_framework import generics, permissions
from rest_framework.response import Response
from core.apps.tasks.serializers.board import BoardSerializer
from core.apps.tasks.models import Column
class BoardListView(generics.ListAPIView):
queryset = Column.objects.order_by('id')
serializer_class = BoardSerializer
permission_classes = [permissions.IsAuthenticated]

View File

@@ -0,0 +1,47 @@
from django.db import transaction
from rest_framework import generics, permissions
from rest_framework.response import Response
from drf_spectacular.utils import extend_schema
from core.apps.tasks.serializers.column import ColumnSerializer
from core.apps.tasks.models.column import Column
@extend_schema(tags=['Tasks'])
class ColumnCreateApiView(generics.GenericAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = ColumnSerializer
@transaction.atomic
def post(self, request):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
column = serializer.save()
return Response(serializer.data)
@extend_schema(tags=['Tasks'])
class ColumnListApiView(generics.ListAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = ColumnSerializer
def get_queryset(self):
return Column.objects.order_by('id')
@extend_schema(tags=['Tasks'])
class ColumnUpdateApiView(generics.UpdateAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = ColumnSerializer
lookup_field = 'id'
queryset = Column.objects.all()
@extend_schema(tags=['Tasks'])
class ColumnDeleteApiView(generics.DestroyAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = ColumnSerializer
lookup_field = 'id'
queryset = Column.objects.all()

View File

@@ -0,0 +1,51 @@
from rest_framework import generics, permissions
from rest_framework.exceptions import PermissionDenied
from core.apps.tasks.models.comment import Comment
from core.apps.tasks.serializers.comment import CommentSerializer, CommentCreateSerializer
class CommentListCreateAPIView(generics.ListCreateAPIView):
queryset = Comment.objects.all()
permission_classes = [permissions.IsAuthenticated]
def get_serializer_class(self):
if self.request.method == 'POST':
return CommentCreateSerializer
return CommentSerializer
def get_queryset(self):
task_id = self.request.query_params.get('task_id')
queryset = self.queryset
if task_id:
queryset = queryset.filter(task_id=task_id)
return queryset.order_by('-id')
def get_serializer_context(self):
return {"request": self.request}
class CommentDetailAPIView(generics.RetrieveUpdateDestroyAPIView):
queryset = Comment.objects.all()
permission_classes = [permissions.IsAuthenticated]
def get_serializer_class(self):
if self.request.method in ['PUT', 'PATCH']:
return CommentCreateSerializer
return CommentSerializer
def get_serializer_context(self):
return {"request": self.request}
def perform_update(self, serializer):
comment = self.get_object()
if comment.created_by != self.request.user:
raise PermissionDenied("You cannot edit this comment")
serializer.save()
def perform_destroy(self, instance):
if instance.created_by != self.request.user:
raise PermissionDenied("You cannot delete this comment")
instance.delete()

View File

@@ -0,0 +1,22 @@
from rest_framework import generics, permissions
from rest_framework.response import Response
from drf_spectacular.utils import extend_schema
from core.apps.tasks.serializers.label import LabelSerializer
from core.apps.tasks.models.label import Label
@extend_schema(tags=['Tasks'])
class LabelListCreateApiView(generics.ListCreateAPIView):
queryset = Label.objects.order_by('id')
serializer_class = LabelSerializer
permission_classes = [permissions.IsAuthenticated]
@extend_schema(tags=['Tasks'])
class LabelRetrieveUpdateDestroyApiView(generics.RetrieveUpdateDestroyAPIView):
queryset = Label.objects.order_by('id')
serializer_class = LabelSerializer
permission_classes = [permissions.IsAuthenticated]
lookup_field = 'id'

View File

@@ -0,0 +1,40 @@
from django.db import transaction
from rest_framework import permissions, generics
from rest_framework.response import Response
from drf_spectacular.utils import extend_schema
from core.apps.tasks.models.task import Task
from core.apps.tasks.serializers.task import TaskSerializer, TaskCreateSerializer
@extend_schema(tags=['Tasks'])
class TaskCreateView(generics.GenericAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = TaskCreateSerializer
queryset = Task.objects.order_by('id')
@transaction.atomic
def post(self, request):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
@extend_schema(tags=['Tasks'])
class TaskListView(generics.ListAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = TaskSerializer
queryset = Task.objects.order_by('id')
def serializer_context(self):
return self.serializer_class(context={"request": self.request})
@extend_schema(tags=['Tasks'])
class TaskDetailView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = TaskSerializer
queryset = Task.objects.order_by('id')

View File

@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: auto.proto
# Protobuf Python Version: 6.31.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import runtime_version as _runtime_version
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
31,
1,
'',
'auto.proto'
)
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nauto.proto\x12\x04\x61uto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xba\x01\n\x12\x41utoAvgCostRequest\x12\r\n\x05\x62rand\x18\x01 \x01(\t\x12\x11\n\tcondition\x18\x02 \x01(\t\x12\r\n\x05model\x18\x03 \x01(\t\x12\x14\n\x0c\x63omplication\x18\x04 \x01(\t\x12\x34\n\x10manufacture_date\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x18\n\x10\x64istance_covered\x18\x06 \x01(\t\x12\r\n\x05\x63olor\x18\x07 \x01(\t\"$\n\x13\x41\x64ImageListResponse\x12\r\n\x05image\x18\x01 \x01(\t\"t\n\x0e\x41\x64ListResponse\x12\n\n\x02id\x18\x01 \x01(\t\x12)\n\x06images\x18\x02 \x03(\x0b\x32\x19.auto.AdImageListResponse\x12\r\n\x05title\x18\x03 \x01(\t\x12\r\n\x05price\x18\x04 \x01(\t\x12\r\n\x05model\x18\x05 \x01(\t\"J\n\x13\x41utoAvgCostResponse\x12\x10\n\x08\x61vg_cost\x18\x01 \x01(\x01\x12!\n\x03\x61\x64s\x18\x02 \x03(\x0b\x32\x14.auto.AdListResponse2X\n\x12\x41utoAvgCostService\x12\x42\n\x0b\x41utoAvgCost\x12\x18.auto.AutoAvgCostRequest\x1a\x19.auto.AutoAvgCostResponseb\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'auto_pb2', _globals)
if not _descriptor._USE_C_DESCRIPTORS:
DESCRIPTOR._loaded_options = None
_globals['_AUTOAVGCOSTREQUEST']._serialized_start=54
_globals['_AUTOAVGCOSTREQUEST']._serialized_end=240
_globals['_ADIMAGELISTRESPONSE']._serialized_start=242
_globals['_ADIMAGELISTRESPONSE']._serialized_end=278
_globals['_ADLISTRESPONSE']._serialized_start=280
_globals['_ADLISTRESPONSE']._serialized_end=396
_globals['_AUTOAVGCOSTRESPONSE']._serialized_start=398
_globals['_AUTOAVGCOSTRESPONSE']._serialized_end=472
_globals['_AUTOAVGCOSTSERVICE']._serialized_start=474
_globals['_AUTOAVGCOSTSERVICE']._serialized_end=562
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,97 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
import warnings
from core.generated import auto_pb2 as auto__pb2
GRPC_GENERATED_VERSION = '1.80.0'
GRPC_VERSION = grpc.__version__
_version_not_supported = False
try:
from grpc._utilities import first_version_is_lower
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
except ImportError:
_version_not_supported = True
if _version_not_supported:
raise RuntimeError(
f'The grpc package installed is at version {GRPC_VERSION},'
+ ' but the generated code in auto_pb2_grpc.py depends on'
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
)
class AutoAvgCostServiceStub(object):
"""Missing associated documentation comment in .proto file."""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.AutoAvgCost = channel.unary_unary(
'/auto.AutoAvgCostService/AutoAvgCost',
request_serializer=auto__pb2.AutoAvgCostRequest.SerializeToString,
response_deserializer=auto__pb2.AutoAvgCostResponse.FromString,
_registered_method=True)
class AutoAvgCostServiceServicer(object):
"""Missing associated documentation comment in .proto file."""
def AutoAvgCost(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_AutoAvgCostServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'AutoAvgCost': grpc.unary_unary_rpc_method_handler(
servicer.AutoAvgCost,
request_deserializer=auto__pb2.AutoAvgCostRequest.FromString,
response_serializer=auto__pb2.AutoAvgCostResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'auto.AutoAvgCostService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
server.add_registered_method_handlers('auto.AutoAvgCostService', rpc_method_handlers)
# This class is part of an EXPERIMENTAL API.
class AutoAvgCostService(object):
"""Missing associated documentation comment in .proto file."""
@staticmethod
def AutoAvgCost(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(
request,
target,
'/auto.AutoAvgCostService/AutoAvgCost',
auto__pb2.AutoAvgCostRequest.SerializeToString,
auto__pb2.AutoAvgCostResponse.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True)

View File

@@ -0,0 +1,54 @@
from datetime import datetime
import grpc
from google.protobuf.timestamp_pb2 import Timestamp
from datetime import datetime
from config.env import env
from core.generated import auto_pb2, auto_pb2_grpc
def get_auto_avg_cost(
brand,
condition,
model,
complication,
manufacture_date: datetime,
distance_covered,
color
):
channel = grpc.insecure_channel("94.230.232.47:50051")
stub = auto_pb2_grpc.AutoAvgCostServiceStub(channel)
ts = Timestamp()
if isinstance(manufacture_date, datetime):
dt = manufacture_date
else:
dt = datetime.combine(manufacture_date, datetime.min.time())
ts.FromDatetime(dt)
response = stub.AutoAvgCost(auto_pb2.AutoAvgCostRequest(
brand=brand,
condition=condition,
model=model,
complication=complication,
manufacture_date=ts,
distance_covered=distance_covered,
color=color,
))
print("manufacture_date:", manufacture_date, type(manufacture_date))
return {
"avg_cost": response.avg_cost,
"ads": [
{
"id": ad.id,
"title": ad.title,
"price": ad.price,
"model": ad.model,
"images": [img.image for img in ad.images],
}
for ad in response.ads
]
}

View File

@@ -46,3 +46,7 @@ boto3
# !NOTE: on-websocket # !NOTE: on-websocket
# websockets # websockets
# channels-redis # channels-redis
grpcio>=1.62.0
grpcio-tools>=1.62.0
protobuf>=4.25.0

View File

@@ -84,7 +84,7 @@ services:
max-file: "5" max-file: "5"
web: web:
image: husanjon/sifatbaho:115 image: husanjon/sifatbaho:147
env_file: env_file:
- .env - .env
environment: environment:
@@ -129,7 +129,7 @@ services:
max-file: "5" max-file: "5"
celery: celery:
image: husanjon/sifatbaho:115 image: husanjon/sifatbaho:147
env_file: env_file:
- .env - .env
environment: environment: