105 Commits

Author SHA1 Message Date
Husanjonazamov
8409992afc test migrate 2026-03-10 13:04:20 +05:00
github-actions[bot]
6525a14ca6 🔄 Update image to 45 [CI SKIP] 2026-03-10 07:13:04 +00:00
5bb3dcd432 Merge pull request 'feat(auto-evaluation): to'liq CRUD API va 4 bosqichli forma qo'shildi' (#25) from feat/auto-evaluation-api into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m8s
Reviewed-on: #25
2026-03-10 07:11:18 +00:00
Husanjonazamov
5c2fe032d0 feat(auto-evaluation): to'liq CRUD API va 4 bosqichli forma qo'shildi
- 10 ta yangi choice klass qo'shildi: ObjectOwnerType, PropertyRights,
  FormOwnership, LocationHighways, LocationConvenience, AutoCarType, AutoCarWheel
- AutoEvaluationModel ga ~30 ta yangi field qo'shildi (4 bosqich):
  1-bosqich: ro'yxatga olish raqami, sanalar, ob'ekt turi
  2-bosqich: egasi ma'lumotlari (jismoniy/yuridik), mulk huquqi, egalik shakli
  3-bosqich: manzil (viloyat, tuman, shahar, mahalla, ko'cha, uy)
  4-bosqich: avtomobil (tex passport, marka, model, raqam, rang, dvigatel)
- CreateSerializer ga validatsiya qo'shildi:
  passport formati (AA 1234567), tex passport formati (AAA 1234567),
  egasi turiga qarab majburiy fieldlar (jismoniy yoki yuridik)
- View ReadOnlyModelViewSet dan ModelViewSet ga o'zgartirildi
- Admin 4 bosqichli fieldset bilan yangilandi
- Yangi filterlar: object_owner_type, property_rights, form_ownership
- VehicleModel fieldlari FK → ReferenceitemModel ga o'tkazildi
- Migratsiyalar: 0015, 0016, 0017
2026-03-10 12:10:28 +05:00
github-actions[bot]
b3581233c1 🔄 Update image to 44 [CI SKIP] 2026-03-09 11:22:03 +00:00
8d30162e87 Merge pull request 'fix test error' (#24) from fix/reference into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m7s
Reviewed-on: #24
2026-03-09 11:20:19 +00:00
Husanjonazamov
44f53649cd fix test error 2026-03-09 16:19:53 +05:00
460e3158b8 Merge pull request 'feat: add ReferenceItem model and update QuickEvaluation FKs' (#23) from feat/quick-evaluation-create-api into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 1m24s
Reviewed-on: #23
2026-03-09 11:04:38 +00:00
Husanjonazamov
3798037240 feat: add ReferenceItem model and update QuickEvaluation FKs
- Create ReferenceitemModel with type, name, parent (self FK), order, is_active fields
- Add ReferenceType choices: brand, marka, color, fuel_type, body_type, car_position, state_car
- Implement ReferenceItem API (list, retrieve) with filter by type/parent/is_active, search, ordering
- Add ReferenceItem admin with list_filter, search, inline editing
- Change QuickEvaluation FK fields from shared.OptionsModel to evaluation.ReferenceitemModel
- Update serializers and views to use .name instead of .key
- Add ReferenceItem to unfold admin navigation
2026-03-09 16:04:15 +05:00
github-actions[bot]
fd2ecd953a 🔄 Update image to 42 [CI SKIP] 2026-03-09 08:32:20 +00:00
9d405330c6 Merge pull request 'feat: add search, filter, sort and pagination to QuickEvaluation list API' (#22) from feat/quick-evaluation-list-api into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 1m50s
Reviewed-on: #22
2026-03-09 08:30:49 +00:00
Husanjonazamov
8feee78ce4 feat: add search, filter, sort and pagination to QuickEvaluation list API 2026-03-09 13:21:55 +05:00
github-actions[bot]
1e67a9f86e 🔄 Update image to 41 [CI SKIP] 2026-03-09 07:30:29 +00:00
9c176674f9 Merge pull request 'tezkor avto baholanganlarni id bo'yicha olish uchun api qoshilfi' (#21) from feat/quick-evaluation-detail-api into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 1m53s
Reviewed-on: #21
2026-03-09 07:28:57 +00:00
Husanjonazamov
04d5b92ac5 tezkor avto baholanganlarni id bo'yicha olish uchun api qoshilfi 2026-03-09 12:26:29 +05:00
github-actions[bot]
50e085fcfd 🔄 Update image to 40 [CI SKIP] 2026-03-05 09:58:13 +00:00
13ba9dcae4 Merge pull request 'log file va test ad file togirilafi' (#20) from fix/cicd-stockv2 into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m8s
Reviewed-on: #20
2026-03-05 09:56:27 +00:00
Husanjonazamov
3707e10ccf log file va test ad file togirilafi 2026-03-05 14:56:06 +05:00
github-actions[bot]
1d275b9907 🔄 Update image to 39 [CI SKIP] 2026-03-02 07:36:37 +00:00
1ccee92417 Merge pull request 'hamma modellarda get serizlizers uchun fiedl qoshilfi' (#19) from feat/get-serializers into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 5m0s
Reviewed-on: #19
2026-03-02 07:31:58 +00:00
Husanjonazamov
1a90803527 hamma modellarda get serizlizers uchun fiedl qoshilfi 2026-03-02 12:31:16 +05:00
github-actions[bot]
8d4eea1dfa 🔄 Update image to 38 [CI SKIP] 2026-02-23 12:43:23 +00:00
cabd159774 Merge pull request 'serach tigurkladfi' (#18) from feat/ad-forms into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m22s
Reviewed-on: #18
2026-02-23 12:41:22 +00:00
Husanjonazamov
e51dd1f952 serach tigurkladfi 2026-02-23 17:40:50 +05:00
github-actions[bot]
a92a2599c7 🔄 Update image to 37 [CI SKIP] 2026-02-18 13:19:30 +00:00
cdf2f40a9c Merge pull request 'admin fayllari to'g'irlandi' (#17) from feat/all-admins into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 3m7s
Reviewed-on: #17
2026-02-18 13:16:45 +00:00
Husanjonazamov
cba724e2d0 admin fayllari to'g'irlandi 2026-02-18 18:16:20 +05:00
github-actions[bot]
cd3037e55f 🔄 Update image to 36 [CI SKIP] 2026-02-18 13:10:40 +00:00
7b05f1f99e Merge pull request 'payment modeli yaratildi' (#16) from feat/payment-model into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 3m52s
Reviewed-on: #16
2026-02-18 13:07:08 +00:00
Husanjonazamov
a6d7fa8c9a payment modeli yaratildi 2026-02-18 18:06:42 +05:00
github-actions[bot]
fbe798043c 🔄 Update image to 35 [CI SKIP] 2026-02-18 13:00:29 +00:00
d4d8c18a2a Merge pull request 'ValuationDocumentModel' (#15) from feat/evaluation-document-model into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 3m18s
Reviewed-on: #15
2026-02-18 12:57:32 +00:00
Husanjonazamov
4680581e8d ValuationDocumentModel
— bu arizaga biriktiriladigan hujjatlar va rasmlar uchun kerak
2026-02-18 17:56:51 +05:00
github-actions[bot]
b3d864d8c1 🔄 Update image to 34 [CI SKIP] 2026-02-18 12:49:24 +00:00
88bcbc07bd Merge pull request 'feat(evaluation): baholash modellari yaratildi (auto, ko'chmas mulk, ko'char mulk, tezkor, hisobot)' (#14) from feat/evaluation-report-model into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m24s
Reviewed-on: #14
2026-02-18 12:47:20 +00:00
Husanjonazamov
4ddd4f138f feat(evaluation): baholash modellari yaratildi (auto, ko'chmas mulk, ko'char mulk, tezkor, hisobot) 2026-02-18 17:44:15 +05:00
github-actions[bot]
3ef3f8fd3f 🔄 Update image to 33 [CI SKIP] 2026-02-13 13:38:28 +00:00
627f7eb9c4 Merge pull request 'QuickEvaluationModel modeli qoshildi shu tezkor baholash uchun ishatiladi' (#13) from feat/evaluation-quick-model into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 3m45s
Reviewed-on: #13
2026-02-13 13:35:04 +00:00
Husanjonazamov
53b0737ee5 QuickEvaluationModel modeli qoshildi shu tezkor baholash uchun ishatiladi 2026-02-13 18:33:56 +05:00
github-actions[bot]
8c7861ca9f 🔄 Update image to 32 [CI SKIP] 2026-02-13 13:01:56 +00:00
97e5850bf7 Merge pull request 'movable-model qoshildi bu (Ko'char mulk) modeli to'liq va optimallashgan holda tayyor!' (#12) from feat/evaluation-movable-model into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 3m51s
Reviewed-on: #12
2026-02-13 12:58:25 +00:00
Husanjonazamov
2cb094cbd3 movable-model qoshildi bu (Ko'char mulk) modeli to'liq va optimallashgan holda tayyor! 2026-02-13 17:57:56 +05:00
github-actions[bot]
9282197c84 🔄 Update image to 31 [CI SKIP] 2026-02-13 12:47:03 +00:00
7d975a0acc Merge pull request 'RealEstateEvaluationModel modeli qoshildi (Ko'chmas mulk (Real Estate) baholash modeli uchun quyidagicha nomlarni tavsiya qilaman:' (#11) from feat/evaluation-real-estate-models into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 3m4s
Reviewed-on: #11
2026-02-13 12:44:18 +00:00
Husanjonazamov
799b5e5cf1 RealEstateEvaluationModel modeli qoshildi (Ko'chmas mulk (Real Estate) baholash modeli uchun quyidagicha nomlarni tavsiya qilaman:
)
2026-02-13 17:43:04 +05:00
github-actions[bot]
e6c64f9621 🔄 Update image to 30 [CI SKIP] 2026-02-13 12:26:10 +00:00
e2e7c23987 Merge pull request 'AutoEvaluationModel qoshildi yani bu valuation bilan vehicle ni asosiy ulab beradigan model' (#10) from feat/evaluation-auto-model into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 3m11s
Reviewed-on: #10
2026-02-13 12:23:18 +00:00
Husanjonazamov
c36a2318a1 AutoEvaluationModel qoshildi yani bu valuation bilan vehicle ni asosiy ulab beradigan model 2026-02-13 17:22:47 +05:00
github-actions[bot]
166bb7240d 🔄 Update image to 29 [CI SKIP] 2026-02-13 11:49:48 +00:00
e074a9abfa Merge pull request '.env.example o'zgartirildi' (#9) from feat/example into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m5s
Reviewed-on: #9
2026-02-13 11:48:03 +00:00
Husanjonazamov
d6299ae378 .env.example o'zgartirildi 2026-02-13 16:47:34 +05:00
github-actions[bot]
1b62e969e2 🔄 Update image to 28 [CI SKIP] 2026-02-13 10:58:33 +00:00
782f14a4a9 Merge pull request 'cicd da deploy yaml togirlandi' (#8) from fix/ci-cd into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 4m55s
Reviewed-on: #8
2026-02-13 10:53:58 +00:00
github-actions[bot]
5158c0ebd0 🔄 Update image to 27 [CI SKIP] 2026-02-13 10:43:17 +00:00
Husanjonazamov
68089a5b6a cicd da deploy yaml togirlandi 2026-02-13 15:42:32 +05:00
88e5ad17bd Merge pull request 'valuation va vihicle modellari qoshildi' (#7) from feat/evaluation-core into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 4m56s
Reviewed-on: #7
2026-02-13 10:38:41 +00:00
Husanjonazamov
acf426ee9b valuation va vihicle modellari qoshildi 2026-02-13 15:38:13 +05:00
github-actions[bot]
4bc54f1952 🔄 Update image to 26 [CI SKIP] 2026-02-12 14:36:47 +00:00
Husanjonazamov
93dcaaf511 fix: postgres version 17-alpine
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m53s
2026-02-12 19:34:00 +05:00
github-actions[bot]
2d0c9766a1 🔄 Update image to 25 [CI SKIP] 2026-02-12 14:18:44 +00:00
Husanjonazamov
58399a8f9f fix: deploy yaml GITEATOKEN secret
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m57s
2026-02-12 19:15:56 +05:00
github-actions[bot]
eab5e591ff 🔄 Update image to 24 [CI SKIP] 2026-02-12 14:01:44 +00:00
Husanjonazamov
aca1599d78 cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 4m4s
2026-02-12 18:57:38 +05:00
github-actions[bot]
925e0b0bba 🔄 Update image to 23 [CI SKIP] 2026-02-12 13:46:15 +00:00
Husanjonazamov
ac51403c1d cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m46s
2026-02-12 18:43:29 +05:00
github-actions[bot]
a8503b5e15 🔄 Update image to 22 [CI SKIP] 2026-02-12 13:25:10 +00:00
Husanjonazamov
8600daf8fa cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m48s
2026-02-12 18:22:24 +05:00
github-actions[bot]
09bc83d975 🔄 Update image to 21 [CI SKIP] 2026-02-12 13:16:39 +00:00
Husanjonazamov
7f46c5ac28 cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m52s
2026-02-12 18:13:49 +05:00
github-actions[bot]
4fc5840727 🔄 Update image to 20 [CI SKIP] 2026-02-12 13:08:46 +00:00
Husanjonazamov
33d1a904b9 cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m4s
2026-02-12 18:06:44 +05:00
github-actions[bot]
7e9f61b18f 🔄 Update image to 19 [CI SKIP] 2026-02-12 13:00:39 +00:00
Husanjonazamov
97545c5a46 cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m51s
2026-02-12 17:57:46 +05:00
github-actions[bot]
630c89e790 🔄 Update image to 18 [CI SKIP] 2026-02-12 12:52:18 +00:00
Husanjonazamov
d16b853830 cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 3m39s
2026-02-12 17:48:37 +05:00
github-actions[bot]
8e5ba3786d 🔄 Update image to 17 [CI SKIP] 2026-02-12 12:27:07 +00:00
Husanjonazamov
862eacad0b cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m3s
2026-02-12 17:25:03 +05:00
github-actions[bot]
895aa0d1de 🔄 Update image to 16 [CI SKIP] 2026-02-12 12:20:51 +00:00
Husanjonazamov
5cc54f0530 cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 3m34s
2026-02-12 17:17:20 +05:00
github-actions[bot]
b6b724739a 🔄 Update image to 15 [CI SKIP] 2026-02-12 12:13:36 +00:00
Husanjonazamov
725da2dc36 cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m52s
2026-02-12 17:10:16 +05:00
github-actions[bot]
39946be25e 🔄 Update image to 14 [CI SKIP] 2026-02-12 11:51:21 +00:00
Husanjonazamov
fc60d5ac8f fix: deploy yaml port va evaluation models yangilandi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m1s
2026-02-12 16:48:58 +05:00
github-actions[bot]
31fc8dec9d 🔄 Update image to 13 [CI SKIP] 2026-02-12 11:43:20 +00:00
Husanjonazamov
d9d3f73870 cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m48s
2026-02-12 16:40:27 +05:00
github-actions[bot]
e84250d539 🔄 Update image to 12 [CI SKIP] 2026-02-12 11:36:13 +00:00
Husanjonazamov
aa3137fa4e cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 1m52s
2026-02-12 16:34:18 +05:00
github-actions[bot]
7c0db33485 🔄 Update image to 11 [CI SKIP] 2026-02-12 11:29:47 +00:00
Husanjonazamov
10a8106312 cicd port ozgardi
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m51s
2026-02-12 16:26:53 +05:00
github-actions[bot]
e32f58ca0d 🔄 Update image to 10 [CI SKIP] 2026-02-12 11:17:11 +00:00
b6182b1cf8 Merge pull request 'cicd port ozgardi' (#6) from feat/testv1 into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m50s
Reviewed-on: #6
2026-02-12 11:14:29 +00:00
Husanjonazamov
2d00559656 cicd port ozgardi 2026-02-12 16:13:57 +05:00
github-actions[bot]
4e26fb1d24 🔄 Update image to 9 [CI SKIP] 2026-02-12 10:57:03 +00:00
fc5c8f02b0 Merge pull request 'cicd port ozgardi' (#5) from feat/test into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m7s
Reviewed-on: #5
2026-02-12 10:55:03 +00:00
Husanjonazamov
e304376e99 cicd port ozgardi 2026-02-12 15:54:40 +05:00
github-actions[bot]
6b6b5d6866 🔄 Update image to 8 [CI SKIP] 2026-02-12 10:43:15 +00:00
3f6268c023 Merge pull request 'cicd port ozgardi' (#4) from feat/cicd-deploy into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m4s
Reviewed-on: #4
2026-02-12 10:41:19 +00:00
Husanjonazamov
fe64830a7d cicd port ozgardi 2026-02-12 15:40:52 +05:00
github-actions[bot]
559208b450 🔄 Update image to 7 [CI SKIP] 2026-02-12 10:35:23 +00:00
f885c66cf6 Merge pull request 'evaluation-customer modeli yaratildi va kerakli fiealdlr qoshildi' (#3) from feat/evaluation-customer into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 4m44s
Reviewed-on: #3
2026-02-12 10:30:45 +00:00
Husanjonazamov
b685800087 evaluation-customer modeli yaratildi va kerakli fiealdlr qoshildi 2026-02-12 15:29:58 +05:00
d2c6ecd772 Merge pull request 'userga role qoshildi' (#2) from feat/users into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 2m41s
Reviewed-on: #2
2026-02-12 08:32:44 +00:00
bf335946cd Merge pull request 'evalution app yaratildi' (#1) from feat/evaluation into main
Some checks failed
Deploy to Production / build-and-deploy (push) Has been cancelled
Reviewed-on: #1
2026-02-12 08:32:32 +00:00
Husanjonazamov
6c296857ae evalution app yaratildi 2026-02-12 13:31:49 +05:00
Husanjonazamov
e3a306bdaa userga role qoshildi 2026-02-12 13:23:38 +05:00
222 changed files with 7004 additions and 70 deletions

View File

@@ -50,7 +50,7 @@ SMS_PASSWORD=key
# Addition # Addition
ALLOWED_HOSTS=127.0.0.1,web ALLOWED_HOSTS=127.0.0.1,web
CSRF_TRUSTED_ORIGINS=http://127.0.0.1:8081 CSRF_TRUSTED_ORIGINS=http://127.0.0.1:8081,https://sifatbaho.felixits.uz
OTP_MODULE=core.services.otp OTP_MODULE=core.services.otp
@@ -73,3 +73,6 @@ STORAGE_BUCKET_STATIC=name
STORAGE_PATH=127.0.0.1:8081/bucket/ STORAGE_PATH=127.0.0.1:8081/bucket/
STORAGE_PROTOCOL=http: STORAGE_PROTOCOL=http:
# Celery configs

View File

@@ -92,9 +92,10 @@ jobs:
- name: Update stack.yaml and version - name: Update stack.yaml and version
run: | run: |
sed -i 's|image: ${{ secrets.DOCKER_USERNAME }}/${{ env.PROJECT_NAME }}:.*|image: ${{ secrets.DOCKER_USERNAME }}/${{ env.PROJECT_NAME }}:${{ github.run_number }}|' 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]"
@@ -112,44 +113,47 @@ jobs:
key: ${{ secrets.KEY }} key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }} port: ${{ secrets.PORT }}
script: | script: |
PROJECTS=/opt/projects/ set -e
DIR=/opt/projects/${{ env.PROJECT_NAME }}/
if [ -d "$PROJECTS" ]; then PROJECTS=/opt/projects
echo "projects papkasi mavjud" DIR=/opt/projects/${{ env.PROJECT_NAME }}
else REPO_URL=https://${{ secrets.GITEATOKEN }}@gitea.felixits.uz/${{ github.repository }}.git
mkdir -p $PROJECTS
echo "projects papkasi yaratildi"
fi
if [ -d "$DIR" ]; then mkdir -p "$PROJECTS"
if [ -d "$DIR/.git" ]; then
echo "loyiha mavjud" echo "loyiha mavjud"
else else
cd $PROJECTS rm -rf "$DIR"
git clone git@gitea.felixits.uz:${{ github.repository }}.git ${{ env.PROJECT_NAME }} cd "$PROJECTS"
echo "Clone qilindi"; git clone "$REPO_URL" "${{ env.PROJECT_NAME }}"
echo "Clone qilindi"
fi fi
cd $DIR cd "$DIR"
git remote set-url origin "$REPO_URL"
git fetch origin main git fetch origin main
git reset --hard origin/main git reset --hard origin/main
cp .env.example .env cp .env.example .env
update_env() { update_env() {
local env_file=".env" local env_file=".env"
cp .env.example "$env_file" for kv in "$@"; do
local key="${kv%%=*}"
for kv in "$@"; do local value="${kv#*=}"
local key="${kv%%=*}" if grep -q "^$key=" "$env_file"; then
local value="${kv#*=}" sed -i "s|^$key=.*|$key=$value|" "$env_file"
sed -i "s|^$key=.*|$key=$value|" "$env_file" else
done echo "$key=$value" >> "$env_file"
fi
done
} }
update_env \ update_env \
"DB_HOST=postgres" \ "DB_HOST=postgres" \
"DB_NAME=sifatbaho" \ "DB_NAME=sifatbahodb" \
"DB_PORT=5432" "DB_PORT=5432"
export PORT=8084 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

2
.gitignore vendored
View File

@@ -2,7 +2,7 @@ node_modules
# OS ignores # OS ignores
*.DS_Store *.DS_Store
#sa
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
*.py[cod] *.py[cod]

114
API_ENDPOINTS.md Normal file
View File

@@ -0,0 +1,114 @@
# SifatBaho — GET API Endpoints
> Barcha endpointlar hozirda `AllowAny` permission bilan ishlaydi.
> Token yuborish shart emas (hozircha).
> Base URL: `http://localhost:8000/api/v1/`
---
## 🔐 Auth (Autentifikatsiya)
| # | URL | Method | Tavsif |
|---|-----|--------|--------|
| 1 | `api/v1/auth/token/` | POST | Login — access va refresh token olish |
| 2 | `api/v1/auth/token/refresh/` | POST | Access tokenni yangilash |
| 3 | `api/v1/auth/token/verify/` | POST | Tokenni tekshirish |
---
## 👤 Buyurtmachilar
| # | URL | Method | Token | Tavsif |
|---|-----|--------|-------|--------|
| 1 | `api/v1/customer/` | GET | ❌ | Barcha buyurtmachilar ro'yxati (ism, INN, JSHSHIR) |
| 2 | `api/v1/customer/{id}/` | GET | ❌ | Bitta buyurtmachining to'liq ma'lumotlari (passport, manzil, bank) |
| 3 | `api/v1/property-owner/` | GET | ❌ | Barcha mulk egalari ro'yxati |
| 4 | `api/v1/property-owner/{id}/` | GET | ❌ | Bitta mulk egasining to'liq ma'lumotlari |
---
## 📋 Arizalar (Valuation)
| # | URL | Method | Token | Tavsif |
|---|-----|--------|-------|--------|
| 5 | `api/v1/valuation/` | GET | ❌ | Barcha arizalar ro'yxati (raqam, tur, status, narx) |
| 6 | `api/v1/valuation/{id}/` | GET | ❌ | Bitta arizaning to'liq ma'lumotlari (buyurtmachi, baholovchi, narxlar) |
---
## 🚗 Transport vositalari
| # | URL | Method | Token | Tavsif |
|---|-----|--------|-------|--------|
| 7 | `api/v1/vehicle/` | GET | ❌ | Barcha transportlar ro'yxati (marka, model, raqam, rang) |
| 8 | `api/v1/vehicle/{id}/` | GET | ❌ | Bitta transportning to'liq ma'lumotlari (VIN, tex passport, yurgan km) |
---
## 🔧 Avto baholash
| # | URL | Method | Token | Tavsif |
|---|-----|--------|-------|--------|
| 9 | `api/v1/auto-evaluation/` | GET | ❌ | Barcha avto baholashlar (ariza + moshina bog'lanishi) |
| 10 | `api/v1/auto-evaluation/{id}/` | GET | ❌ | Bitta avto baholash detali (ariza va moshina to'liq) |
---
## 🏠 Ko'chmas mulk baholash
| # | URL | Method | Token | Tavsif |
|---|-----|--------|-------|--------|
| 11 | `api/v1/real-estate-evaluation/` | GET | ❌ | Barcha ko'chmas mulk baholashlar (tur, manzil, maydon) |
| 12 | `api/v1/real-estate-evaluation/{id}/` | GET | ❌ | Bitta ko'chmas mulk detali (kadastr, qavat, xonalar) |
---
## 📦 Ko'char mulk baholash
| # | URL | Method | Token | Tavsif |
|---|-----|--------|-------|--------|
| 13 | `api/v1/movable-property-evaluation/` | GET | ❌ | Barcha ko'char mulk baholashlar (nomi, kategoriya, soni) |
| 14 | `api/v1/movable-property-evaluation/{id}/` | GET | ❌ | Bitta ko'char mulk detali (seriya raqami, holat) |
---
## ⚡ Tezkor baholash
| # | URL | Method | Token | Tavsif |
|---|-----|--------|-------|--------|
| 15 | `api/v1/quick-evaluation/` | GET | ❌ | Barcha tezkor baholashlar (marka, model, taxminiy narx) |
| 16 | `api/v1/quick-evaluation/{id}/` | GET | ❌ | Bitta tezkor baholash detali (VIN, yoqilg'i turi, holat) |
---
## 📄 Hisobotlar
| # | URL | Method | Token | Tavsif |
|---|-----|--------|-------|--------|
| 17 | `api/v1/evaluation-report/` | GET | ❌ | Barcha hisobotlar ro'yxati (raqam, baholovchi, yakuniy narx) |
| 18 | `api/v1/evaluation-report/{id}/` | GET | ❌ | Bitta hisobot detali (xulosa matni, PDF fayl) |
---
## 📎 Ariza hujjatlari
| # | URL | Method | Token | Tavsif |
|---|-----|--------|-------|--------|
| 19 | `api/v1/valuation-document/` | GET | ❌ | Barcha hujjatlar ro'yxati (turi, sarlavha, fayl) |
| 20 | `api/v1/valuation-document/{id}/` | GET | ❌ | Bitta hujjat detali (tavsif, kim yuklagan) |
---
## 💳 To'lovlar
| # | URL | Method | Token | Tavsif |
|---|-----|--------|-------|--------|
| 21 | `api/v1/payment/` | GET | ❌ | Barcha to'lovlar ro'yxati (summa, usul, status) |
| 22 | `api/v1/payment/{id}/` | GET | ❌ | Bitta to'lov detali (tranzaksiya ID, izoh) |
---
**Jami: 22 ta GET endpoint** (11 ta List + 11 ta Detail)
> ⚠️ Hozir barcha endpointlar `AllowAny` — token kerak emas.
> Keyinchalik `IsAuthenticated` ga o'zgartiriladi.

32
MODELS.md Normal file
View File

@@ -0,0 +1,32 @@
# SifatBaho — Modellar Ro'yxati
## Evaluation App — 11 ta model
| # | Model nomi | Fayl | Vazifasi |
|---|-----------|------|----------|
| 1 | `CustomerModel` | `models/customer.py` | Buyurtmachi (jismoniy yoki yuridik shaxs). Ariza beruvchi mijozning shaxsiy ma'lumotlari saqlanadi. |
| 2 | `PropertyOwnerModel` | `models/customer.py` | Mulk egasi. Agar buyurtmachi va mulk egasi boshqa odam bo'lsa, shu model to'ldiriladi. |
| 3 | `ValuationModel` | `models/valuation.py` | Asosiy ariza. Barcha baholash turlari uchun umumiy model: status, narx, buyurtmachi, baholovchi. |
| 4 | `VehicleModel` | `models/vehicle.py` | Transport vositasi. Moshinaning texnik ma'lumotlari: VIN, davlat raqami, marka, model, rang, yurgan masofasi. |
| 5 | `AutoEvaluationModel` | `models/auto.py` | Avto baholash bog'lamasi. Arizani moshinaga bog'laydi (Ariza + Vehicle = AutoEvaluation). |
| 6 | `RealEstateEvaluationModel` | `models/real_estate.py` | Ko'chmas mulk baholash. Uy, xonadon, ofis uchun: maydoni, qavati, kadastr raqami, manzili. |
| 7 | `MovablePropertyEvaluationModel` | `models/movable.py` | Ko'char mulk baholash. Uskunalar, mebellar, stanoklar uchun: nomi, kategoriyasi, seriya raqami, miqdori. |
| 8 | `QuickEvaluationModel` | `models/quick.py` | Tezkor baholash. To'liq ariza yaratmasdan, moshina narxini taxminiy hisoblab beradi (kalkulyator). |
| 9 | `EvaluationReportModel` | `models/report.py` | Yakuniy hisobot. Baholovchi tomonidan tayyorlanadigan rasmiy natija: yakuniy narx, PDF fayl, xulosa matni. |
| 10 | `ValuationDocumentModel` | `models/document.py` | Ariza hujjatlari. Arizaga biriktiriladigan fayllar: passport, tex passport, rasmlar, guvohnomalar. |
## Payment App — 1 ta model
| # | Model nomi | Fayl | Vazifasi |
|---|-----------|------|----------|
| 11 | `PaymentModel` | `models/payment.py` | To'lov. Ariza uchun to'lov ma'lumotlari: summa, to'lov usuli (Click/Payme/naqd), tranzaksiya ID, status. |
## Accounts App — 1 ta model (mavjud edi)
| # | Model nomi | Fayl | Vazifasi |
|---|-----------|------|----------|
| 12 | `User` | `models/user.py` | Foydalanuvchi. Tizimga kirish, rollar (admin, baholovchi, diler, mijoz). |
---
**Jami: 12 ta model** — barchasi TZ asosida yaratildi va ishlamoqda. ✅

View File

@@ -1,3 +1 @@
MODULES = [ MODULES = ["core.apps.shared", "core.apps.evaluation", "core.apps.payment"]
"core.apps.shared",
]

View File

@@ -6,26 +6,116 @@ PAGES = [
"seperator": False, "seperator": False,
"items": [ "items": [
{ {
"title": _("Home page"), "title": _("Bosh sahifa"),
"icon": "home", "icon": "home",
"link": reverse_lazy("admin:index"), "link": reverse_lazy("admin:index"),
} }
], ],
}, },
{ {
"title": _("Auth"), "title": _("Foydalanuvchilar"),
"separator": True, # Top border "separator": True,
"items": [ "items": [
{ {
"title": _("Users"), "title": _("Foydalanuvchilar"),
"icon": "group", "icon": "group",
"link": reverse_lazy("admin:http_user_changelist"), "link": reverse_lazy("admin:accounts_user_changelist"),
}, },
{ {
"title": _("Group"), "title": _("Guruhlar"),
"icon": "group", "icon": "admin_panel_settings",
"link": reverse_lazy("admin:auth_group_changelist"), "link": reverse_lazy("admin:auth_group_changelist"),
}, },
], ],
}, },
{
"title": _("Buyurtmachilar"),
"separator": True,
"items": [
{
"title": _("Buyurtmachilar"),
"icon": "person",
"link": reverse_lazy("admin:evaluation_customermodel_changelist"),
},
{
"title": _("Mulk egalari"),
"icon": "badge",
"link": reverse_lazy("admin:evaluation_propertyownermodel_changelist"),
},
],
},
{
"title": _("Arizalar"),
"separator": True,
"items": [
{
"title": _("Barcha arizalar"),
"icon": "description",
"link": reverse_lazy("admin:evaluation_valuationmodel_changelist"),
},
{
"title": _("Ariza hujjatlari"),
"icon": "attach_file",
"link": reverse_lazy("admin:evaluation_valuationdocumentmodel_changelist"),
},
],
},
{
"title": _("Baholash turlari"),
"separator": True,
"items": [
{
"title": _("Avto baholash"),
"icon": "directions_car",
"link": reverse_lazy("admin:evaluation_autoevaluationmodel_changelist"),
},
{
"title": _("Transport vositalari"),
"icon": "car_repair",
"link": reverse_lazy("admin:evaluation_vehiclemodel_changelist"),
},
{
"title": _("Ko'chmas mulk"),
"icon": "home_work",
"link": reverse_lazy("admin:evaluation_realestateevaluationmodel_changelist"),
},
{
"title": _("Ko'char mulk"),
"icon": "inventory_2",
"link": reverse_lazy("admin:evaluation_movablepropertyevaluationmodel_changelist"),
},
{
"title": _("Tezkor baholash"),
"icon": "bolt",
"link": reverse_lazy("admin:evaluation_quickevaluationmodel_changelist"),
},
],
},
{
"title": _("Natijalar"),
"separator": True,
"items": [
{
"title": _("Hisobotlar"),
"icon": "summarize",
"link": reverse_lazy("admin:evaluation_evaluationreportmodel_changelist"),
},
{
"title": _("To'lovlar"),
"icon": "payments",
"link": reverse_lazy("admin:payment_paymentmodel_changelist"),
},
],
},
{
"title": _("Ma'lumotnomalari"),
"separator": True,
"items": [
{
"title": _("Ma'lumotnomalar"),
"icon": "category",
"link": reverse_lazy("admin:evaluation_referenceitemmodel_changelist"),
},
],
},
] ]

View File

@@ -90,6 +90,6 @@ UNFOLD = {
"SIDEBAR": { "SIDEBAR": {
"show_search": True, "show_search": True,
"show_all_applications": True, "show_all_applications": True,
# "navigation": navigation.PAGES, "navigation": navigation.PAGES,
}, },
} }

View File

@@ -2,32 +2,27 @@
All urls configurations tree All urls configurations tree
""" """
from config.env import env
from django.conf import settings from django.conf import settings
from django.contrib import admin from django.contrib import admin
from django.http import HttpResponse from django.http import HttpResponse
from django.urls import include, path, re_path from django.urls import include, path, re_path
from django.views.static import serve from django.views.static import serve
from drf_spectacular.views import (SpectacularAPIView, SpectacularRedocView, from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
SpectacularSwaggerView)
from config.env import env
def home(request): def home(request):
return HttpResponse("OK") return HttpResponse("OK: #5bb3dcd432ba0c045e6f2ef91c23bd4a16a1d256")
################
# My apps url
################
urlpatterns = [ urlpatterns = [
path("health/", home), path("health/", home),
path("api/v1/", include("core.apps.accounts.urls")), path("api/v1/", include("core.apps.accounts.urls")),
path("api/", include("core.apps.shared.urls")), path("api/", include("core.apps.shared.urls")),
path("api/v1/", include("core.apps.evaluation.urls")),
path("api/v1/", include("core.apps.payment.urls")),
] ]
################
# Library urls
################
urlpatterns += [ urlpatterns += [
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
path("accounts/", include("django.contrib.auth.urls")), path("accounts/", include("django.contrib.auth.urls")),
@@ -35,29 +30,15 @@ urlpatterns += [
path("rosetta/", include("rosetta.urls")), path("rosetta/", include("rosetta.urls")),
path("ckeditor5/", include("django_ckeditor_5.urls"), name="ck_editor_5_upload_file"), path("ckeditor5/", include("django_ckeditor_5.urls"), name="ck_editor_5_upload_file"),
] ]
################
# Project env debug mode
################
if env.bool("SILK_ENABLED", False): if env.bool("SILK_ENABLED", False):
urlpatterns += [ urlpatterns += []
]
if env.str("PROJECT_ENV") == "debug": if env.str("PROJECT_ENV") == "debug":
################
# Swagger urls
################
urlpatterns += [ urlpatterns += [
path("schema/", SpectacularAPIView.as_view(), name="schema"), path("schema/", SpectacularAPIView.as_view(), name="schema"),
path("swagger/", SpectacularSwaggerView.as_view(url_name="schema"), name="swagger-ui"), path("swagger/", SpectacularSwaggerView.as_view(url_name="schema"), name="swagger-ui"),
path("redoc/", SpectacularRedocView.as_view(url_name="schema"), name="redoc"), path("redoc/", SpectacularRedocView.as_view(url_name="schema"), name="redoc"),
] ]
################
# Media urls
################
urlpatterns += [ urlpatterns += [
re_path(r"static/(?P<path>.*)", serve, {"document_root": settings.STATIC_ROOT}), re_path("static/(?P<path>.*)", serve, {"document_root": settings.STATIC_ROOT}),
re_path(r"media/(?P<path>.*)", serve, {"document_root": settings.MEDIA_ROOT}), re_path("media/(?P<path>.*)", serve, {"document_root": settings.MEDIA_ROOT}),
] ]

View File

@@ -14,5 +14,6 @@ admin.site.unregister(db_models.Group)
admin.site.register(db_models.Group, user.GroupAdmin) admin.site.register(db_models.Group, user.GroupAdmin)
admin.site.register(db_models.Permission, user.PermissionAdmin) admin.site.register(db_models.Permission, user.PermissionAdmin)
admin.site.register(get_user_model(), user.CustomUserAdmin) admin.site.register(get_user_model(), user.CustomUserAdmin)
admin.site.register(SmsConfirm, SmsConfirmAdmin) admin.site.register(SmsConfirm, SmsConfirmAdmin)

View File

@@ -15,6 +15,7 @@ class CustomUserAdmin(admin.UserAdmin, ModelAdmin):
"phone", "phone",
"role", "role",
) )
search_fields = ("phone", "first_name", "last_name", "username")
autocomplete_fields = ["groups", "user_permissions"] autocomplete_fields = ["groups", "user_permissions"]
fieldsets = ((None, {"fields": ("phone",)}),) + ( fieldsets = ((None, {"fields": ("phone",)}),) + (
(None, {"fields": ("username", "password")}), (None, {"fields": ("username", "password")}),
@@ -37,7 +38,7 @@ class CustomUserAdmin(admin.UserAdmin, ModelAdmin):
class PermissionAdmin(ModelAdmin): class PermissionAdmin(ModelAdmin):
list_display = ("name",) list_display = ("name",)
search_fields = ("name",) search_fields = ("name",)

View File

@@ -10,3 +10,6 @@ class RoleChoice(models.TextChoices):
SUPERUSER = "superuser", _("Superuser") SUPERUSER = "superuser", _("Superuser")
ADMIN = "admin", _("Admin") ADMIN = "admin", _("Admin")
USER = "user", _("User") USER = "user", _("User")
EVALUATOR = "evaluator", _("Evaluator")
DEALER = "dealer", _("Dealer")
CLIENT = "client", _("Client")

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.7 on 2026-02-12 10:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='user',
name='role',
field=models.CharField(choices=[('superuser', 'Superuser'), ('admin', 'Admin'), ('user', 'User'), ('evaluator', 'Evaluator'), ('dealer', 'Dealer'), ('client', 'Client')], default='user', max_length=255),
),
]

View File

View File

@@ -0,0 +1,10 @@
from .auto import * # noqa
from .customer import * # noqa
from .document import * # noqa
from .movable import * # noqa
from .quick import * # noqa
from .real_estate import * # noqa
from .reference import * # noqa
from .report import * # noqa
from .valuation import * # noqa
from .vehicle import * # noqa

View File

@@ -0,0 +1,75 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.evaluation.models import AutoEvaluationModel
@admin.register(AutoEvaluationModel)
class AutoEvaluationAdmin(ModelAdmin):
list_display = (
"id",
"registration_number",
"object_type",
"car_brand",
"car_model",
"car_number",
"status",
"created_at",
)
list_filter = ("status", "object_type", "rate_type", "value_determined", "object_owner_type")
search_fields = (
"registration_number",
"car_brand",
"car_model",
"car_number",
)
readonly_fields = ("created_at", "updated_at")
autocomplete_fields = ("valuation", "vehicle")
fieldsets = (
("Bog'lanishlar", {
"classes": ("collapse",),
"fields": ("valuation", "vehicle"),
}),
("Step 1 — Umumiy ma'lumotlar", {
"fields": (
"registration_number",
("contract_date", "object_inspection_date"),
("rate_date", "rate_report_date"),
"rate_object_name",
"object_type",
"status",
),
}),
("Step 2 — Shaxs ma'lumotlari", {
"fields": (
"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"),
("property_rights", "form_ownership"),
("value_determined", "rate_type"),
),
}),
("Step 3 — Manzil ma'lumotlari", {
"fields": (
("object_location_province", "object_location_district"),
("object_location_city", "object_location_neighborhood"),
("object_location_street", "object_location_home"),
("object_location_highways", "object_location_covenience"),
),
}),
("Step 4 — Avtomobil ma'lumotlari", {
"fields": (
"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"),
),
}),
("Tizim", {
"classes": ("collapse",),
"fields": ("created_at", "updated_at"),
}),
)

View File

@@ -0,0 +1,108 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.evaluation.models import CustomerModel, PropertyOwnerModel
@admin.register(CustomerModel)
class CustomerAdmin(ModelAdmin):
list_display = (
"id",
"customer_type",
"first_name",
"last_name",
"jshshir",
"inn",
"org_name",
"created_at",
)
list_filter = ("customer_type",)
search_fields = (
"first_name",
"last_name",
"jshshir",
"passport_number",
"inn",
"org_name",
)
readonly_fields = ("created_at", "updated_at")
fieldsets = (
("Umumiy", {
"fields": ("customer_type",),
}),
("Jismoniy shaxs", {
"fields": (
"jshshir",
("passport_series", "passport_number"),
("first_name", "last_name", "middle_name"),
"address",
("passport_issued_date", "passport_issued_by"),
),
}),
("Yuridik shaxs", {
"fields": (
"inn",
"org_name",
"org_address",
"director_name",
("mfo", "bank_account"),
"certificate_file",
),
}),
("Tizim", {
"classes": ("collapse",),
"fields": ("created_at", "updated_at"),
}),
)
@admin.register(PropertyOwnerModel)
class PropertyOwnerAdmin(ModelAdmin):
list_display = (
"id",
"owner_type",
"first_name",
"last_name",
"jshshir",
"inn",
"org_name",
"created_at",
)
list_filter = ("owner_type",)
search_fields = (
"first_name",
"last_name",
"jshshir",
"passport_number",
"inn",
"org_name",
)
readonly_fields = ("created_at", "updated_at")
fieldsets = (
("Umumiy", {
"fields": ("owner_type",),
}),
("Jismoniy shaxs", {
"fields": (
"jshshir",
("passport_series", "passport_number"),
("first_name", "last_name", "middle_name"),
"address",
("passport_issued_date", "passport_issued_by"),
),
}),
("Yuridik shaxs", {
"fields": (
"inn",
"org_name",
"org_address",
"director_name",
("mfo", "bank_account"),
"certificate_file",
),
}),
("Tizim", {
"classes": ("collapse",),
"fields": ("created_at", "updated_at"),
}),
)

View File

@@ -0,0 +1,42 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.evaluation.models import ValuationDocumentModel
@admin.register(ValuationDocumentModel)
class ValuationDocumentAdmin(ModelAdmin):
list_display = (
"id",
"valuation",
"document_type",
"title",
"uploaded_by",
"created_at",
)
list_filter = ("document_type",)
search_fields = (
"title",
"description",
"valuation__conclusion_number",
)
readonly_fields = ("created_at", "updated_at")
autocomplete_fields = ("valuation", "uploaded_by")
fieldsets = (
("Hujjat", {
"fields": (
"valuation",
"document_type",
"title",
"file",
"uploaded_by",
),
}),
("Qo'shimcha", {
"fields": ("description",),
}),
("Tizim", {
"classes": ("collapse",),
"fields": ("created_at", "updated_at"),
}),
)

View File

@@ -0,0 +1,50 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.evaluation.models import MovablePropertyEvaluationModel
@admin.register(MovablePropertyEvaluationModel)
class MovablePropertyEvaluationAdmin(ModelAdmin):
list_display = (
"id",
"valuation",
"property_name",
"property_category",
"serial_number",
"manufacture_year",
"condition",
"quantity",
)
list_filter = (
"property_category",
"condition",
)
search_fields = (
"property_name",
"serial_number",
"valuation__conclusion_number",
)
readonly_fields = ("created_at", "updated_at")
autocomplete_fields = ("valuation",)
fieldsets = (
("Ariza", {
"fields": ("valuation",),
}),
("Mulk ma'lumotlari", {
"fields": (
"property_name",
"property_category",
"serial_number",
"manufacture_year",
"quantity",
),
}),
("Holat", {
"fields": ("condition",),
}),
("Tizim", {
"classes": ("collapse",),
"fields": ("created_at", "updated_at"),
}),
)

View File

@@ -0,0 +1,67 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.evaluation.models import QuickEvaluationModel
@admin.register(QuickEvaluationModel)
class QuickEvaluationAdmin(ModelAdmin):
list_display = (
"id",
"created_by",
"brand",
"marka",
"car_number",
"car_manufactured_date",
"estimated_price",
"status",
"car_type",
"state_car",
"created_at",
)
list_filter = (
"status",
"car_type",
)
search_fields = (
"car_number",
"vin_number",
"engine_number",
"tex_passport_serie_num",
)
readonly_fields = ("created_at", "updated_at")
autocomplete_fields = ("created_by",)
fieldsets = (
("Foydalanuvchi", {
"fields": ("created_by",),
}),
("Tex passport", {
"fields": (
"tex_passport_serie_num",
("tech_passport_issued_date", "tech_passport_issued_place"),
"tex_passport_file",
),
}),
("Transport ma'lumotlari", {
"fields": (
"car_number",
("brand", "marka"),
("car_manufactured_date", "color"),
("vin_number", "engine_number"),
("distance_covered", "car_position"),
),
}),
("Texnik holat", {
"fields": (
("fuel_type", "body_type"),
("car_type", "state_car"),
),
}),
("Natija", {
"fields": ("estimated_price", "status"),
}),
("Tizim", {
"classes": ("collapse",),
"fields": ("created_at", "updated_at"),
}),
)

View File

@@ -0,0 +1,60 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.evaluation.models import RealEstateEvaluationModel
@admin.register(RealEstateEvaluationModel)
class RealEstateEvaluationAdmin(ModelAdmin):
list_display = (
"id",
"valuation",
"property_type",
"address",
"total_area",
"floor",
"build_year",
"condition",
)
list_filter = (
"property_type",
"condition",
"has_renovation",
)
search_fields = (
"address",
"cadastral_number",
"valuation__conclusion_number",
)
readonly_fields = ("created_at", "updated_at")
autocomplete_fields = ("valuation",)
fieldsets = (
("Ariza", {
"fields": ("valuation",),
}),
("Mulk ma'lumotlari", {
"fields": (
"property_type",
"address",
"cadastral_number",
),
}),
("Texnik parametrlar", {
"fields": (
("total_area", "living_area"),
("floor", "total_floors"),
"rooms_count",
"build_year",
),
}),
("Holat", {
"fields": (
"condition",
"has_renovation",
),
}),
("Tizim", {
"classes": ("collapse",),
"fields": ("created_at", "updated_at"),
}),
)

View File

@@ -0,0 +1,18 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.evaluation.models import ReferenceitemModel
@admin.register(ReferenceitemModel)
class ReferenceitemAdmin(ModelAdmin):
list_display = ("id", "type", "name", "parent", "order", "is_active")
list_filter = ("type", "is_active")
search_fields = ("name",)
list_editable = ("order", "is_active")
autocomplete_fields = ("parent",)
fieldsets = (
(None, {
"fields": ("type", "name", "parent", "order", "is_active"),
}),
)

View File

@@ -0,0 +1,50 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.evaluation.models import EvaluationReportModel
@admin.register(EvaluationReportModel)
class EvaluationReportAdmin(ModelAdmin):
list_display = (
"id",
"report_number",
"valuation",
"evaluator",
"final_value",
"approved_at",
"created_at",
)
list_filter = ("approved_at",)
search_fields = (
"report_number",
"valuation__conclusion_number",
"evaluator__phone",
"evaluator__first_name",
"conclusion_text",
)
readonly_fields = ("created_at", "updated_at")
autocomplete_fields = ("valuation", "evaluator")
fieldsets = (
("Hisobot", {
"fields": (
"report_number",
"valuation",
"evaluator",
),
}),
("Natija", {
"fields": (
"final_value",
"conclusion_text",
"report_file",
),
}),
("Tasdiqlash", {
"fields": ("approved_at",),
}),
("Tizim", {
"classes": ("collapse",),
"fields": ("created_at", "updated_at"),
}),
)

View File

@@ -0,0 +1,73 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.evaluation.models import ValuationModel
@admin.register(ValuationModel)
class ValuationAdmin(ModelAdmin):
list_display = (
"id",
"conclusion_number",
"evaluation_type",
"status",
"customer",
"assigned_to",
"estimated_price",
"final_price",
"payment_status",
"created_at",
)
list_filter = (
"evaluation_type",
"status",
"payment_status",
"evaluation_purpose",
"is_courier_delivery",
)
search_fields = (
"conclusion_number",
"customer__first_name",
"customer__last_name",
"customer__org_name",
"customer__inn",
)
readonly_fields = ("created_at", "updated_at")
autocomplete_fields = ("customer", "property_owner", "created_by", "assigned_to")
fieldsets = (
("Asosiy ma'lumotlar", {
"fields": (
"conclusion_number",
("evaluation_type", "evaluation_subtype"),
"evaluation_purpose",
"status",
),
}),
("Bog'lanishlar", {
"fields": (
"customer",
"property_owner",
"created_by",
"assigned_to",
),
}),
("Narx va To'lov", {
"fields": (
("estimated_price", "final_price"),
"payment_status",
),
}),
("Yetkazib berish", {
"fields": (
"is_courier_delivery",
"courier_extra_amount",
),
}),
("Qo'shimcha", {
"fields": ("notes",),
}),
("Tizim", {
"classes": ("collapse",),
"fields": ("created_at", "updated_at"),
}),
)

View File

@@ -0,0 +1,61 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from core.apps.evaluation.models import VehicleModel
@admin.register(VehicleModel)
class VehicleAdmin(ModelAdmin):
list_display = (
"id",
"brand",
"model",
"license_plate",
"manufacture_year",
"color",
"fuel_type",
"condition",
"mileage",
)
list_filter = (
"condition",
"manufacture_year",
)
search_fields = (
"brand__name",
"model__name",
"license_plate",
"vin_number",
"engine_number",
"tech_passport_number",
)
readonly_fields = ("created_at", "updated_at")
autocomplete_fields = ("brand", "model", "color", "fuel_type", "body_type", "position")
fieldsets = (
("Texnik passport", {
"fields": (
("tech_passport_series", "tech_passport_number"),
("tech_passport_issued_date", "tech_passport_issued_by"),
),
}),
("Transport ma'lumotlari", {
"fields": (
("brand", "model"),
"license_plate",
("manufacture_year", "color"),
("vin_number", "engine_number"),
"position",
),
}),
("Texnik holat", {
"fields": (
("fuel_type", "body_type"),
"condition",
"mileage",
),
}),
("Tizim", {
"classes": ("collapse",),
"fields": ("created_at", "updated_at"),
}),
)

View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class ModuleConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "core.apps.evaluation"

View File

@@ -0,0 +1,70 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
class AutoObjectType(models.TextChoices):
LIGHTWEIGHT_AUTO = "lightweight_auto", _("Yengil automobil")
TRUCK_CAR = "truck_car", _("Yuk automobil")
SPECIAL_TECH = "special_tech", _("Maxsus texnika")
class AutoEvaluationStatus(models.TextChoices):
CREATED = "yaratildi", _("Yaratildi")
EVALUATOR_ASSIGNED = "baxolovchi_biriktirildi", _("Baholovchi biriktirildi")
EVALUATED = "baxolandi", _("Baholandi")
REJECTED = "rad_etildi", _("Rad etildi")
APPROVED = "tasdiqlandi", _("Tasdiqlandi")
class ObjectOwnerType(models.IntegerChoices):
INDIVIDUAL = 1, _("Jismoniy shaxs")
LEGAL = 2, _("Yuridik shaxs")
class PropertyRights(models.IntegerChoices):
PERMANENT_OWNERSHIP = 1, _("Doimiy egalik")
PERMANENT_USE = 2, _("Doimiy foydalanish")
TEMPORARY_USE = 3, _("Vaqtinchalik foydalanish")
TERM_LEASE = 4, _("Muddatli ijara")
LIFETIME_INHERITANCE = 5, _("Umrbod meros qilib olish")
class FormOwnership(models.IntegerChoices):
PRIVATE = 1, _("Xususiy")
STATE = 2, _("Davlat")
JSC = 3, _("AJ")
LLC = 4, _("MCHJ")
OTHER = 5, _("Boshqa")
class ValueDetermined(models.IntegerChoices):
MARKET_VALUE = 1, _("Bozor qiymati")
TAX_PURPOSE = 2, _("Soliq maqsadlari uchun")
LIQUIDATION_VALUE = 3, _("Tugatish qiymati")
UTILIZATION_VALUE = 4, _("Utilizatsiya qiymati")
class RateType(models.IntegerChoices):
CREDIT_COLLATERAL = 1, _("Kredit ta'minoti sifatida garovga qo'yish")
SALE_PURPOSE = 2, _("Sotish maqsadida bozor qiymatini aniqlash")
TAX_PURPOSE = 3, _("Soliqqa tortish maqsadida")
OTHER = 4, _("Boshqa")
class LocationHighways(models.IntegerChoices):
CENTER = 1, _("Tuman/Shahar markazi")
FAR_FROM_CENTER = 2, _("Tuman/shahar markazidan uzoqda")
class LocationConvenience(models.IntegerChoices):
POPULATED_AREA = 1, _("Aholi gavjum hudud")
MARKET_AREA = 2, _("Bozor hududi")
class AutoCarType(models.IntegerChoices):
HATCHBACK = 1, _("Xetchbek")
UNIVERSAL = 2, _("Universal")
class AutoCarWheel(models.IntegerChoices):
FOUR_BY_FOUR = 1, _("4x4")

View File

@@ -0,0 +1,13 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
class DocumentType(models.TextChoices):
CERTIFICATE = "certificate", _("Certificate")
PASSPORT = "passport", _("Passport")
TECH_PASSPORT = "tech_passport", _("Tech Passport")
CADASTRAL = "cadastral", _("Cadastral Document")
PHOTO = "photo", _("Photo")
CONTRACT = "contract", _("Contract")
POWER_OF_ATTORNEY = "power_of_attorney", _("Power of Attorney")
OTHER = "other", _("Other")

View File

@@ -0,0 +1,19 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
class MovablePropertyCategory(models.TextChoices):
EQUIPMENT = "equipment", _("Equipment")
MACHINERY = "machinery", _("Machinery")
FURNITURE = "furniture", _("Furniture")
ELECTRONICS = "electronics", _("Electronics")
COMMODITY = "commodity", _("Commodity/Goods")
OTHER = "other", _("Other")
class MovablePropertyCondition(models.TextChoices):
NEW = "new", _("New")
GOOD = "good", _("Good")
AVERAGE = "average", _("Average")
POOR = "poor", _("Poor/Needs repair")
SCRAP = "scrap", _("Scrap")

View File

@@ -0,0 +1,17 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
class QuickEvaluationStatus(models.TextChoices):
CREATED = "created", _("Created")
EVALUATOR_ASSIGNED = "evaluator_assigned", _("Evaluator assigned")
EVALUATED = "evaluated", _("Evaluated")
REJECTED = "rejected", _("Rejected")
APPROVED = "approved", _("Approved")
class CarType(models.TextChoices):
LIGHTWEIGHT = "lightweight", _("Lightweight")
TRUCK = "truck", _("Truck")
BUS = "bus", _("Bus")
MOTO = "moto", _("Moto")

View File

@@ -0,0 +1,18 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
class PropertyType(models.TextChoices):
APARTMENT = "apartment", _("Apartment")
HOUSE = "house", _("House")
OFFICE = "office", _("Office")
LAND = "land", _("Land")
COMMERCIAL = "commercial", _("Commercial")
INDUSTRIAL = "industrial", _("Industrial")
class RealEstateCondition(models.TextChoices):
NEW = "new", _("New (Rough finish)")
FINISHED = "finished", _("Finished (Standard/Euro)")
REPAIR_REQUIRED = "repair_required", _("Needs repair")
UNDER_CONSTRUCTION = "under_construction", _("Under construction")

View File

@@ -0,0 +1,12 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
class ReferenceType(models.TextChoices):
BRAND = "brand", _("Brand")
MARKA = "marka", _("Marka")
COLOR = "color", _("Color")
FUEL_TYPE = "fuel_type", _("Fuel type")
BODY_TYPE = "body_type", _("Body type")
CAR_POSITION = "car_position", _("Car position")
STATE_CAR = "state_car", _("Car state")

View File

@@ -0,0 +1,33 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
class EvaluationPurpose(models.TextChoices):
SALE = "sale", _("Sale")
BANK = "bank", _("Bank/Loan")
INSURANCE = "insurance", _("Insurance")
INHERITANCE = "inheritance", _("Inheritance")
COURT = "court", _("Court/Judicial")
OTHER = "other", _("Other")
class EvaluationType(models.TextChoices):
AUTO = "auto", _("Auto")
REAL_ESTATE = "real_estate", _("Real Estate")
MOVABLE_PROPERTY = "movable_property", _("Movable Property")
class ValuationStatus(models.TextChoices):
DRAFT = "draft", _("Draft")
PENDING = "pending", _("Pending")
IN_REVIEW = "in_review", _("In Review")
APPROVED = "approved", _("Approved")
REJECTED = "rejected", _("Rejected")
PAID = "paid", _("Paid")
COMPLETED = "completed", _("Completed")
class PaymentStatus(models.TextChoices):
UNPAID = "unpaid", _("Unpaid")
PENDING = "pending", _("Pending")
PAID = "paid", _("Paid")

View File

@@ -0,0 +1,28 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
class FuelType(models.TextChoices):
PETROL = "petrol", _("Petrol")
DIESEL = "diesel", _("Diesel")
GAS = "gas", _("Gas")
ELECTRIC = "electric", _("Electric")
HYBRID = "hybrid", _("Hybrid")
class BodyType(models.TextChoices):
HATCHBACK = "hatchback", _("Hatchback")
SEDAN = "sedan", _("Sedan")
UNIVERSAL = "universal", _("Universal")
COUPE = "coupe", _("Coupe")
CABRIOLET = "cabriolet", _("Cabriolet")
LIFTBACK = "liftback", _("Liftback")
MINIVAN = "minivan", _("Minivan")
CROSSOVER = "crossover", _("Crossover")
class VehicleCondition(models.TextChoices):
EXCELLENT = "excellent", _("Excellent")
GOOD = "good", _("Good")
AVERAGE = "average", _("Average")
NEEDS_REPAIR = "needs_repair", _("Needs repair")

View File

View File

@@ -0,0 +1,10 @@
from .auto import * # noqa
from .customer import * # noqa
from .document import * # noqa
from .movable import * # noqa
from .quick import * # noqa
from .real_estate import * # noqa
from .reference import * # noqa
from .report import * # noqa
from .valuation import * # noqa
from .vehicle import * # noqa

View File

@@ -0,0 +1,45 @@
from django_filters import rest_framework as filters
from core.apps.evaluation.models import AutoEvaluationModel
class AutoevaluationFilter(filters.FilterSet):
status = filters.CharFilter(method="filter_status")
object_type = filters.CharFilter(field_name="object_type", lookup_expr="exact")
object_owner_type = filters.NumberFilter(field_name="object_owner_type", lookup_expr="exact")
rate_type = filters.NumberFilter(field_name="rate_type", lookup_expr="exact")
value_determined = filters.NumberFilter(field_name="value_determined", lookup_expr="exact")
property_rights = filters.NumberFilter(field_name="property_rights", lookup_expr="exact")
form_ownership = filters.NumberFilter(field_name="form_ownership", lookup_expr="exact")
object_location_province = filters.CharFilter(
field_name="object_location_province", lookup_expr="icontains"
)
client = filters.NumberFilter(field_name="valuation__customer", lookup_expr="exact")
created_from = filters.DateFilter(field_name="created_at", lookup_expr="gte")
created_to = filters.DateFilter(field_name="created_at", lookup_expr="lte")
rate_date_from = filters.DateFilter(field_name="rate_date", lookup_expr="gte")
rate_date_to = filters.DateFilter(field_name="rate_date", lookup_expr="lte")
def filter_status(self, queryset, name, value):
if value:
statuses = [s.strip() for s in value.split(",") if s.strip()]
return queryset.filter(status__in=statuses)
return queryset
class Meta:
model = AutoEvaluationModel
fields = [
"status",
"object_type",
"object_owner_type",
"rate_type",
"value_determined",
"property_rights",
"form_ownership",
"object_location_province",
"client",
"created_from",
"created_to",
"rate_date_from",
"rate_date_to",
]

View File

@@ -0,0 +1,18 @@
from django_filters import rest_framework as filters
from core.apps.evaluation.models import CustomerModel, PropertyOwnerModel
class CustomerFilter(filters.FilterSet):
class Meta:
model = CustomerModel
fields = []
class PropertyOwnerFilter(filters.FilterSet):
class Meta:
model = PropertyOwnerModel
fields = []

View File

@@ -0,0 +1,11 @@
from django_filters import rest_framework as filters
from core.apps.evaluation.models import ValuationDocumentModel
class ValuationdocumentFilter(filters.FilterSet):
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
class Meta:
model = ValuationDocumentModel
fields = []

View File

@@ -0,0 +1,13 @@
# from django_filters import rest_framework as filters
# from core.apps.evaluation.models import MovablePropertyEvaluationModel
# class MovablepropertyevaluationFilter(filters.FilterSet):
# # name = filters.CharFilter(field_name="name", lookup_expr="icontains")
# class Meta:
# model = MovablePropertyEvaluationModel
# fields = [
# "name",
# ]

View File

@@ -0,0 +1,31 @@
from django_filters import rest_framework as filters
from core.apps.evaluation.models import QuickEvaluationModel
class QuickevaluationFilter(filters.FilterSet):
status = filters.CharFilter(method="filter_status")
car_type = filters.CharFilter(field_name="car_type", lookup_expr="exact")
state_car = filters.NumberFilter(field_name="state_car", lookup_expr="exact")
created_from = filters.DateFilter(field_name="created_at", lookup_expr="gte")
created_to = filters.DateFilter(field_name="created_at", lookup_expr="lte")
year_from = filters.NumberFilter(field_name="car_manufactured_date", lookup_expr="gte")
year_to = filters.NumberFilter(field_name="car_manufactured_date", lookup_expr="lte")
def filter_status(self, queryset, name, value):
if value:
statuses = [s.strip() for s in value.split(",") if s.strip()]
return queryset.filter(status__in=statuses)
return queryset
class Meta:
model = QuickEvaluationModel
fields = [
"status",
"car_type",
"state_car",
"created_from",
"created_to",
"year_from",
"year_to",
]

View File

@@ -0,0 +1,11 @@
from django_filters import rest_framework as filters
from core.apps.evaluation.models import RealEstateEvaluationModel
class RealestateevaluationFilter(filters.FilterSet):
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
class Meta:
model = RealEstateEvaluationModel
fields = []

View File

@@ -0,0 +1,17 @@
from django_filters import rest_framework as filters
from core.apps.evaluation.models import ReferenceitemModel
class ReferenceitemFilter(filters.FilterSet):
type = filters.CharFilter(field_name="type", lookup_expr="exact")
parent = filters.NumberFilter(field_name="parent", lookup_expr="exact")
is_active = filters.BooleanFilter(field_name="is_active")
class Meta:
model = ReferenceitemModel
fields = [
"type",
"parent",
"is_active",
]

View File

@@ -0,0 +1,11 @@
from django_filters import rest_framework as filters
from core.apps.evaluation.models import EvaluationReportModel
class EvaluationreportFilter(filters.FilterSet):
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
class Meta:
model = EvaluationReportModel
fields = []

View File

@@ -0,0 +1,11 @@
from django_filters import rest_framework as filters
from core.apps.evaluation.models import ValuationModel
class ValuationFilter(filters.FilterSet):
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
class Meta:
model = ValuationModel
fields = []

View File

@@ -0,0 +1,11 @@
from django_filters import rest_framework as filters
from core.apps.evaluation.models import VehicleModel
class VehicleFilter(filters.FilterSet):
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
class Meta:
model = VehicleModel
fields = []

View File

@@ -0,0 +1,10 @@
from .auto import * # noqa
from .customer import * # noqa
from .document import * # noqa
from .movable import * # noqa
from .quick import * # noqa
from .real_estate import * # noqa
from .reference import * # noqa
from .report import * # noqa
from .valuation import * # noqa
from .vehicle import * # noqa

View File

@@ -0,0 +1,10 @@
from django import forms
from core.apps.evaluation.models import AutoEvaluationModel
class AutoevaluationForm(forms.ModelForm):
class Meta:
model = AutoEvaluationModel
fields = "__all__"

View File

@@ -0,0 +1,18 @@
from django import forms
from core.apps.evaluation.models import CustomerModel, PropertyOwnerModel
class CustomerForm(forms.ModelForm):
class Meta:
model = CustomerModel
fields = "__all__"
class PropertyOwnerForm(forms.ModelForm):
class Meta:
model = PropertyOwnerModel
fields = "__all__"

View File

@@ -0,0 +1,10 @@
from django import forms
from core.apps.evaluation.models import ValuationDocumentModel
class ValuationdocumentForm(forms.ModelForm):
class Meta:
model = ValuationDocumentModel
fields = "__all__"

View File

@@ -0,0 +1,10 @@
from django import forms
from core.apps.evaluation.models import MovablePropertyEvaluationModel
class MovablepropertyevaluationForm(forms.ModelForm):
class Meta:
model = MovablePropertyEvaluationModel
fields = "__all__"

View File

@@ -0,0 +1,10 @@
from django import forms
from core.apps.evaluation.models import QuickEvaluationModel
class QuickevaluationForm(forms.ModelForm):
class Meta:
model = QuickEvaluationModel
fields = "__all__"

View File

@@ -0,0 +1,10 @@
from django import forms
from core.apps.evaluation.models import RealEstateEvaluationModel
class RealestateevaluationForm(forms.ModelForm):
class Meta:
model = RealEstateEvaluationModel
fields = "__all__"

View File

@@ -0,0 +1,10 @@
from django import forms
from core.apps.evaluation.models import ReferenceitemModel
class ReferenceitemForm(forms.ModelForm):
class Meta:
model = ReferenceitemModel
fields = "__all__"

View File

@@ -0,0 +1,10 @@
from django import forms
from core.apps.evaluation.models import EvaluationReportModel
class EvaluationreportForm(forms.ModelForm):
class Meta:
model = EvaluationReportModel
fields = "__all__"

View File

@@ -0,0 +1,10 @@
from django import forms
from core.apps.evaluation.models import ValuationModel
class ValuationForm(forms.ModelForm):
class Meta:
model = ValuationModel
fields = "__all__"

View File

@@ -0,0 +1,10 @@
from django import forms
from core.apps.evaluation.models import VehicleModel
class VehicleForm(forms.ModelForm):
class Meta:
model = VehicleModel
fields = "__all__"

View File

@@ -0,0 +1,42 @@
# Generated by Django 5.2.7 on 2026-02-12 10:18
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='CustomerModel',
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, verbose_name='name')),
],
options={
'verbose_name': 'CustomerModel',
'verbose_name_plural': 'CustomerModels',
'db_table': 'Customer',
},
),
migrations.CreateModel(
name='PropertyownerModel',
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, verbose_name='name')),
],
options={
'verbose_name': 'PropertyownerModel',
'verbose_name_plural': 'PropertyownerModels',
'db_table': 'PropertyOwner',
},
),
]

View File

@@ -0,0 +1,209 @@
# Generated by Django 5.2.7 on 2026-02-12 10:29
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='customermodel',
options={'verbose_name': 'Customer', 'verbose_name_plural': 'Customers'},
),
migrations.AlterModelOptions(
name='propertyownermodel',
options={'verbose_name': 'Property Owner', 'verbose_name_plural': 'Property Owners'},
),
migrations.RemoveField(
model_name='customermodel',
name='name',
),
migrations.RemoveField(
model_name='propertyownermodel',
name='name',
),
migrations.AddField(
model_name='customermodel',
name='address',
field=models.TextField(blank=True, default='', verbose_name='address'),
),
migrations.AddField(
model_name='customermodel',
name='bank_account',
field=models.CharField(blank=True, default='', max_length=30, verbose_name='bank account (HISOB raqam)'),
),
migrations.AddField(
model_name='customermodel',
name='certificate_file',
field=models.FileField(blank=True, null=True, upload_to='customers/certificates/', verbose_name='certificate file (guvohnoma)'),
),
migrations.AddField(
model_name='customermodel',
name='customer_type',
field=models.CharField(choices=[('legal', 'Yuridik shaxs'), ('individual', 'Jismoniy shaxs')], default=1, max_length=20, verbose_name='customer type'),
preserve_default=False,
),
migrations.AddField(
model_name='customermodel',
name='director_name',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='director full name'),
),
migrations.AddField(
model_name='customermodel',
name='first_name',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='first name'),
),
migrations.AddField(
model_name='customermodel',
name='inn',
field=models.CharField(blank=True, default='', max_length=20, verbose_name='INN'),
),
migrations.AddField(
model_name='customermodel',
name='jshshir',
field=models.CharField(blank=True, default='', max_length=14, verbose_name='JSHSHIR'),
),
migrations.AddField(
model_name='customermodel',
name='last_name',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='last name'),
),
migrations.AddField(
model_name='customermodel',
name='mfo',
field=models.CharField(blank=True, default='', max_length=10, verbose_name='MFO'),
),
migrations.AddField(
model_name='customermodel',
name='middle_name',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='middle name'),
),
migrations.AddField(
model_name='customermodel',
name='org_address',
field=models.TextField(blank=True, default='', verbose_name='organization address'),
),
migrations.AddField(
model_name='customermodel',
name='org_name',
field=models.CharField(blank=True, default='', max_length=500, verbose_name='organization name'),
),
migrations.AddField(
model_name='customermodel',
name='passport_issued_by',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='passport issued by'),
),
migrations.AddField(
model_name='customermodel',
name='passport_issued_date',
field=models.DateField(blank=True, null=True, verbose_name='passport issued date'),
),
migrations.AddField(
model_name='customermodel',
name='passport_number',
field=models.CharField(blank=True, default='', max_length=20, verbose_name='passport number'),
),
migrations.AddField(
model_name='customermodel',
name='passport_series',
field=models.CharField(blank=True, default='', max_length=10, verbose_name='passport series'),
),
migrations.AddField(
model_name='propertyownermodel',
name='address',
field=models.TextField(blank=True, default='', verbose_name='address'),
),
migrations.AddField(
model_name='propertyownermodel',
name='bank_account',
field=models.CharField(blank=True, default='', max_length=30, verbose_name='bank account (HISOB raqam)'),
),
migrations.AddField(
model_name='propertyownermodel',
name='certificate_file',
field=models.FileField(blank=True, null=True, upload_to='property_owners/certificates/', verbose_name='certificate file (guvohnoma)'),
),
migrations.AddField(
model_name='propertyownermodel',
name='director_name',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='director full name'),
),
migrations.AddField(
model_name='propertyownermodel',
name='first_name',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='first name'),
),
migrations.AddField(
model_name='propertyownermodel',
name='inn',
field=models.CharField(blank=True, default='', max_length=20, verbose_name='INN'),
),
migrations.AddField(
model_name='propertyownermodel',
name='jshshir',
field=models.CharField(blank=True, default='', max_length=14, verbose_name='JSHSHIR'),
),
migrations.AddField(
model_name='propertyownermodel',
name='last_name',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='last name'),
),
migrations.AddField(
model_name='propertyownermodel',
name='mfo',
field=models.CharField(blank=True, default='', max_length=10, verbose_name='MFO'),
),
migrations.AddField(
model_name='propertyownermodel',
name='middle_name',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='middle name'),
),
migrations.AddField(
model_name='propertyownermodel',
name='org_address',
field=models.TextField(blank=True, default='', verbose_name='organization address'),
),
migrations.AddField(
model_name='propertyownermodel',
name='org_name',
field=models.CharField(blank=True, default='', max_length=500, verbose_name='organization name'),
),
migrations.AddField(
model_name='propertyownermodel',
name='owner_type',
field=models.CharField(choices=[('legal', 'Yuridik shaxs'), ('individual', 'Jismoniy shaxs')], default=1, max_length=20, verbose_name='owner type'),
preserve_default=False,
),
migrations.AddField(
model_name='propertyownermodel',
name='passport_issued_by',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='passport issued by'),
),
migrations.AddField(
model_name='propertyownermodel',
name='passport_issued_date',
field=models.DateField(blank=True, null=True, verbose_name='passport issued date'),
),
migrations.AddField(
model_name='propertyownermodel',
name='passport_number',
field=models.CharField(blank=True, default='', max_length=20, verbose_name='passport number'),
),
migrations.AddField(
model_name='propertyownermodel',
name='passport_series',
field=models.CharField(blank=True, default='', max_length=10, verbose_name='passport series'),
),
migrations.AlterModelTable(
name='customermodel',
table='customer',
),
migrations.AlterModelTable(
name='propertyownermodel',
table='property_owner',
),
]

View File

@@ -0,0 +1,73 @@
# Generated by Django 5.2.7 on 2026-02-13 10:20
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0002_alter_customermodel_options_and_more'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='VehicleModel',
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)),
('tech_passport_series', models.CharField(blank=True, max_length=10, null=True, verbose_name='tech passport series')),
('tech_passport_number', models.CharField(blank=True, max_length=20, null=True, verbose_name='tech passport number')),
('tech_passport_issued_date', models.DateField(blank=True, null=True, verbose_name='tech passport issued date')),
('tech_passport_issued_by', models.CharField(blank=True, max_length=255, null=True, verbose_name='tech passport issued by')),
('license_plate', models.CharField(blank=True, max_length=20, null=True, verbose_name='license plate')),
('brand', models.CharField(blank=True, max_length=100, null=True, verbose_name='brand')),
('model', models.CharField(blank=True, max_length=100, null=True, verbose_name='model')),
('manufacture_year', models.IntegerField(blank=True, null=True, verbose_name='manufacture year')),
('vin_number', models.CharField(blank=True, max_length=25, null=True, verbose_name='VIN number')),
('engine_number', models.CharField(blank=True, max_length=50, null=True, verbose_name='engine number')),
('color', models.CharField(blank=True, max_length=50, null=True, verbose_name='color')),
('mileage', models.IntegerField(blank=True, help_text='Distance in km', null=True, verbose_name='mileage')),
('fuel_type', models.CharField(blank=True, choices=[('petrol', 'Petrol'), ('diesel', 'Diesel'), ('gas', 'Gas'), ('electric', 'Electric'), ('hybrid', 'Hybrid')], max_length=20, null=True, verbose_name='fuel type')),
('body_type', models.CharField(blank=True, choices=[('hatchback', 'Hatchback'), ('sedan', 'Sedan'), ('universal', 'Universal'), ('coupe', 'Coupe'), ('cabriolet', 'Cabriolet'), ('liftback', 'Liftback'), ('minivan', 'Minivan'), ('crossover', 'Crossover')], max_length=20, null=True, verbose_name='body type')),
('condition', models.CharField(blank=True, choices=[('excellent', 'Excellent'), ('good', 'Good'), ('average', 'Average'), ('needs_repair', 'Needs repair')], max_length=20, null=True, verbose_name='condition')),
('position', models.CharField(blank=True, max_length=50, null=True, verbose_name='position')),
],
options={
'verbose_name': 'Vehicle',
'verbose_name_plural': 'Vehicles',
'db_table': 'Vehicle',
},
),
migrations.CreateModel(
name='ValuationModel',
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)),
('conclusion_number', models.CharField(blank=True, max_length=50, null=True, unique=True, verbose_name='conclusion number')),
('evaluation_purpose', models.CharField(choices=[('sale', 'Sale'), ('bank', 'Bank/Loan'), ('insurance', 'Insurance'), ('inheritance', 'Inheritance'), ('court', 'Court/Judicial'), ('other', 'Other')], default='sale', max_length=50, verbose_name='evaluation purpose')),
('evaluation_type', models.CharField(choices=[('auto', 'Auto'), ('real_estate', 'Real Estate'), ('movable_property', 'Movable Property')], max_length=50, verbose_name='evaluation type')),
('evaluation_subtype', models.CharField(blank=True, max_length=100, null=True, verbose_name='evaluation subtype')),
('status', models.CharField(choices=[('draft', 'Draft'), ('pending', 'Pending'), ('in_review', 'In Review'), ('approved', 'Approved'), ('rejected', 'Rejected'), ('paid', 'Paid'), ('completed', 'Completed')], default='draft', max_length=20, verbose_name='status')),
('estimated_price', models.DecimalField(blank=True, decimal_places=2, max_digits=15, null=True, verbose_name='estimated price')),
('final_price', models.DecimalField(blank=True, decimal_places=2, max_digits=15, null=True, verbose_name='final price')),
('payment_status', models.CharField(choices=[('unpaid', 'Unpaid'), ('pending', 'Pending'), ('paid', 'Paid')], default='unpaid', max_length=20, verbose_name='payment status')),
('is_courier_delivery', models.BooleanField(default=False, verbose_name='courier delivery')),
('courier_extra_amount', models.DecimalField(decimal_places=2, default=0, max_digits=12, verbose_name='courier extra amount')),
('notes', models.TextField(blank=True, null=True, verbose_name='notes')),
('assigned_to', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned_valuations', to=settings.AUTH_USER_MODEL, verbose_name='assigned to')),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='created_valuations', to=settings.AUTH_USER_MODEL, verbose_name='created by')),
('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='valuations', to='evaluation.customermodel', verbose_name='customer')),
('property_owner', models.ForeignKey(blank=True, help_text='Keep empty if customer is the owner', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='valuations', to='evaluation.propertyownermodel', verbose_name='property owner')),
],
options={
'verbose_name': 'Valuation',
'verbose_name_plural': 'Valuations',
'db_table': 'Valuation',
},
),
]

View File

@@ -0,0 +1,29 @@
# Generated by Django 5.2.7 on 2026-02-13 12:19
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0003_vehiclemodel_valuationmodel'),
]
operations = [
migrations.CreateModel(
name='AutoEvaluationModel',
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)),
('valuation', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='auto_detail', to='evaluation.valuationmodel', verbose_name='valuation')),
('vehicle', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='evaluation', to='evaluation.vehiclemodel', verbose_name='vehicle')),
],
options={
'verbose_name': 'Auto Evaluation',
'verbose_name_plural': 'Auto Evaluations',
'db_table': 'AutoEvaluation',
},
),
]

View File

@@ -0,0 +1,39 @@
# Generated by Django 5.2.7 on 2026-02-13 12:30
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0004_autoevaluationmodel'),
]
operations = [
migrations.CreateModel(
name='RealEstateEvaluationModel',
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)),
('property_type', models.CharField(choices=[('apartment', 'Apartment'), ('house', 'House'), ('office', 'Office'), ('land', 'Land'), ('commercial', 'Commercial'), ('industrial', 'Industrial')], default='apartment', max_length=50, verbose_name='property type')),
('address', models.TextField(verbose_name='address')),
('cadastral_number', models.CharField(blank=True, max_length=50, null=True, verbose_name='cadastral number')),
('total_area', models.DecimalField(decimal_places=2, max_digits=12, verbose_name='total area')),
('living_area', models.DecimalField(blank=True, decimal_places=2, max_digits=12, null=True, verbose_name='living area')),
('floor', models.IntegerField(blank=True, null=True, verbose_name='floor')),
('total_floors', models.IntegerField(blank=True, null=True, verbose_name='total floors')),
('rooms_count', models.IntegerField(blank=True, null=True, verbose_name='rooms count')),
('build_year', models.IntegerField(blank=True, null=True, verbose_name='build year')),
('condition', models.CharField(blank=True, choices=[('new', 'New (Rough finish)'), ('finished', 'Finished (Standard/Euro)'), ('repair_required', 'Needs repair'), ('under_construction', 'Under construction')], max_length=50, null=True, verbose_name='condition')),
('has_renovation', models.BooleanField(default=False, verbose_name='has renovation')),
('valuation', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='real_estate_detail', to='evaluation.valuationmodel', verbose_name='valuation')),
],
options={
'verbose_name': 'Real Estate Evaluation',
'verbose_name_plural': 'Real Estate Evaluations',
'db_table': 'RealEstateEvaluation',
},
),
]

View File

@@ -0,0 +1,34 @@
# Generated by Django 5.2.7 on 2026-02-13 12:51
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0005_realestateevaluationmodel'),
]
operations = [
migrations.CreateModel(
name='MovablePropertyEvaluationModel',
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)),
('property_name', models.CharField(max_length=255, verbose_name='property name')),
('property_category', models.CharField(choices=[('equipment', 'Equipment'), ('machinery', 'Machinery'), ('furniture', 'Furniture'), ('electronics', 'Electronics'), ('commodity', 'Commodity/Goods'), ('other', 'Other')], default='other', max_length=50, verbose_name='property category')),
('serial_number', models.CharField(blank=True, max_length=100, null=True, verbose_name='serial number')),
('manufacture_year', models.IntegerField(blank=True, null=True, verbose_name='manufacture year')),
('condition', models.CharField(blank=True, choices=[('new', 'New'), ('good', 'Good'), ('average', 'Average'), ('poor', 'Poor/Needs repair'), ('scrap', 'Scrap')], max_length=50, null=True, verbose_name='condition')),
('quantity', models.IntegerField(default=1, verbose_name='quantity')),
('valuation', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='movable_property_detail', to='evaluation.valuationmodel', verbose_name='valuation')),
],
options={
'verbose_name': 'Movable Property Evaluation',
'verbose_name_plural': 'Movable Property Evaluations',
'db_table': 'MovablePropertyEvaluation',
},
),
]

View File

@@ -0,0 +1,43 @@
# Generated by Django 5.2.7 on 2026-02-13 13:31
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0006_movablepropertyevaluationmodel'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='QuickEvaluationModel',
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)),
('tech_passport_number', models.CharField(blank=True, max_length=50, null=True, verbose_name='tech passport number')),
('license_plate', models.CharField(blank=True, max_length=20, null=True, verbose_name='license plate')),
('model', models.CharField(blank=True, max_length=255, null=True, verbose_name='model')),
('brand', models.CharField(blank=True, max_length=255, null=True, verbose_name='brand')),
('manufacture_year', models.IntegerField(blank=True, null=True, verbose_name='manufacture year')),
('mileage', models.IntegerField(blank=True, null=True, verbose_name='mileage')),
('vin_number', models.CharField(blank=True, max_length=50, null=True, verbose_name='VIN number')),
('engine_number', models.CharField(blank=True, max_length=50, null=True, verbose_name='engine number')),
('color', models.CharField(blank=True, max_length=50, null=True, verbose_name='color')),
('fuel_type', models.CharField(blank=True, choices=[('petrol', 'Petrol'), ('diesel', 'Diesel'), ('gas', 'Gas'), ('electric', 'Electric'), ('hybrid', 'Hybrid')], max_length=50, null=True, verbose_name='fuel type')),
('body_type', models.CharField(blank=True, choices=[('hatchback', 'Hatchback'), ('sedan', 'Sedan'), ('universal', 'Universal'), ('coupe', 'Coupe'), ('cabriolet', 'Cabriolet'), ('liftback', 'Liftback'), ('minivan', 'Minivan'), ('crossover', 'Crossover')], max_length=50, null=True, verbose_name='body type')),
('condition', models.CharField(blank=True, choices=[('excellent', 'Excellent'), ('good', 'Good'), ('average', 'Average'), ('needs_repair', 'Needs repair')], max_length=50, null=True, verbose_name='condition')),
('estimated_price', models.DecimalField(blank=True, decimal_places=2, max_digits=15, null=True, verbose_name='estimated price')),
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_evaluations', to=settings.AUTH_USER_MODEL, verbose_name='created by')),
],
options={
'verbose_name': 'Quick Evaluation',
'verbose_name_plural': 'Quick Evaluations',
'db_table': 'QuickEvaluation',
},
),
]

View File

@@ -0,0 +1,36 @@
# Generated by Django 5.2.7 on 2026-02-18 12:34
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0007_quickevaluationmodel'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='EvaluationReportModel',
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)),
('report_number', models.CharField(max_length=100, unique=True, verbose_name='report number')),
('final_value', models.DecimalField(decimal_places=2, max_digits=15, verbose_name='final value')),
('report_file', models.FileField(blank=True, null=True, upload_to='evaluation/reports/', verbose_name='report file')),
('conclusion_text', models.TextField(blank=True, verbose_name='conclusion text')),
('approved_at', models.DateTimeField(blank=True, null=True, verbose_name='approved at')),
('evaluator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='reports', to=settings.AUTH_USER_MODEL, verbose_name='evaluator')),
('valuation', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='report', to='evaluation.valuationmodel', verbose_name='valuation')),
],
options={
'verbose_name': 'Evaluation Report',
'verbose_name_plural': 'Evaluation Reports',
'db_table': 'EvaluationReport',
},
),
]

View File

@@ -0,0 +1,36 @@
# Generated by Django 5.2.7 on 2026-02-18 12:54
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0008_evaluationreportmodel'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='ValuationDocumentModel',
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)),
('document_type', models.CharField(choices=[('certificate', 'Certificate'), ('passport', 'Passport'), ('tech_passport', 'Tech Passport'), ('cadastral', 'Cadastral Document'), ('photo', 'Photo'), ('contract', 'Contract'), ('power_of_attorney', 'Power of Attorney'), ('other', 'Other')], default='other', max_length=50, verbose_name='document type')),
('title', models.CharField(blank=True, max_length=255, verbose_name='title')),
('file', models.FileField(upload_to='evaluation/documents/%Y/%m/', verbose_name='file')),
('description', models.TextField(blank=True, verbose_name='description')),
('uploaded_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='uploaded_documents', to=settings.AUTH_USER_MODEL, verbose_name='uploaded by')),
('valuation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='documents', to='evaluation.valuationmodel', verbose_name='valuation')),
],
options={
'verbose_name': 'Valuation Document',
'verbose_name_plural': 'Valuation Documents',
'db_table': 'ValuationDocument',
'ordering': ['-created_at'],
},
),
]

View File

@@ -0,0 +1,28 @@
# Generated by Django 5.2.7 on 2026-03-09 07:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0009_valuationdocumentmodel'),
]
operations = [
migrations.AddField(
model_name='quickevaluationmodel',
name='car_type',
field=models.CharField(blank=True, choices=[('lightweight', 'Yengil avtomobil'), ('yuk', 'Yuk mashinasi'), ('bus', 'Avtobus'), ('moto', 'Mototsikl')], max_length=50, null=True, verbose_name='car type'),
),
migrations.AddField(
model_name='quickevaluationmodel',
name='state_car',
field=models.CharField(blank=True, choices=[('yaxshi', 'Yaxshi'), ('qoniqarli', 'Qoniqarli'), ('yomon', 'Yomon')], max_length=50, null=True, verbose_name='car state'),
),
migrations.AddField(
model_name='quickevaluationmodel',
name='status',
field=models.CharField(choices=[('yaratildi', 'Yaratildi'), ('baxolovchi_biriktirildi', 'Baxolovchi biriktirildi'), ('baxolandi', 'Baxolandi'), ('rad_etildi', 'Rad etildi'), ('tasdiqlandi', 'Tasdiqlandi')], default='yaratildi', max_length=50, verbose_name='status'),
),
]

View File

@@ -0,0 +1,28 @@
# Generated by Django 5.2.7 on 2026-03-09 08:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0010_add_status_car_type_state_car_to_quick_evaluation'),
]
operations = [
migrations.AlterField(
model_name='quickevaluationmodel',
name='car_type',
field=models.CharField(blank=True, choices=[('lightweight', 'Lightweight'), ('truck', 'Truck'), ('bus', 'Bus'), ('moto', 'Moto')], max_length=50, null=True, verbose_name='car type'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='state_car',
field=models.CharField(blank=True, choices=[('good', 'Good'), ('satisfactory', 'Satisfactory'), ('bad', 'Bad')], max_length=50, null=True, verbose_name='car state'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='status',
field=models.CharField(choices=[('created', 'Created'), ('evaluator_assigned', 'Evaluator assigned'), ('evaluated', 'Evaluated'), ('rejected', 'Rejected'), ('approved', 'Approved')], default='created', max_length=50, verbose_name='status'),
),
]

View File

@@ -0,0 +1,109 @@
# Generated by Django 5.2.7 on 2026-03-09 09:57
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0011_update_choices_to_english'),
('shared', '0002_settingsmodel_created_at_settingsmodel_description_and_more'),
]
operations = [
migrations.RemoveField(
model_name='quickevaluationmodel',
name='condition',
),
migrations.RemoveField(
model_name='quickevaluationmodel',
name='license_plate',
),
migrations.RemoveField(
model_name='quickevaluationmodel',
name='manufacture_year',
),
migrations.RemoveField(
model_name='quickevaluationmodel',
name='mileage',
),
migrations.RemoveField(
model_name='quickevaluationmodel',
name='model',
),
migrations.RemoveField(
model_name='quickevaluationmodel',
name='tech_passport_number',
),
migrations.AddField(
model_name='quickevaluationmodel',
name='car_manufactured_date',
field=models.IntegerField(blank=True, null=True, verbose_name='manufacture year'),
),
migrations.AddField(
model_name='quickevaluationmodel',
name='car_number',
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='car number'),
),
migrations.AddField(
model_name='quickevaluationmodel',
name='car_position',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_positions', to='shared.optionsmodel', verbose_name='car position'),
),
migrations.AddField(
model_name='quickevaluationmodel',
name='distance_covered',
field=models.IntegerField(blank=True, null=True, verbose_name='distance covered (km)'),
),
migrations.AddField(
model_name='quickevaluationmodel',
name='marka',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_markas', to='shared.optionsmodel', verbose_name='marka'),
),
migrations.AddField(
model_name='quickevaluationmodel',
name='tech_passport_issued_date',
field=models.DateField(blank=True, null=True, verbose_name='tech passport issued date'),
),
migrations.AddField(
model_name='quickevaluationmodel',
name='tech_passport_issued_place',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='tech passport issued place'),
),
migrations.AddField(
model_name='quickevaluationmodel',
name='tex_passport_file',
field=models.FileField(blank=True, null=True, upload_to='quick_evaluation/tech_passports/%Y/%m/', verbose_name='tech passport file'),
),
migrations.AddField(
model_name='quickevaluationmodel',
name='tex_passport_serie_num',
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='tech passport series and number'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='body_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_body_types', to='shared.optionsmodel', verbose_name='body type'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='brand',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_brands', to='shared.optionsmodel', verbose_name='brand'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='color',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_colors', to='shared.optionsmodel', verbose_name='color'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='fuel_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_fuel_types', to='shared.optionsmodel', verbose_name='fuel type'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='state_car',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_states', to='shared.optionsmodel', verbose_name='car state'),
),
]

View File

@@ -0,0 +1,33 @@
# Generated by Django 5.2.7 on 2026-03-09 10:49
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0012_remove_quickevaluationmodel_condition_and_more'),
]
operations = [
migrations.CreateModel(
name='ReferenceitemModel',
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=[('brand', 'Brand'), ('marka', 'Marka'), ('color', 'Color'), ('fuel_type', 'Fuel type'), ('body_type', 'Body type'), ('car_position', 'Car position'), ('state_car', 'Car state')], max_length=50, verbose_name='type')),
('name', models.CharField(max_length=255, verbose_name='name')),
('order', models.IntegerField(default=0, verbose_name='order')),
('is_active', models.BooleanField(default=True, verbose_name='is active')),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='evaluation.referenceitemmodel', verbose_name='parent')),
],
options={
'verbose_name': 'Reference Item',
'verbose_name_plural': 'Reference Items',
'db_table': 'ReferenceItem',
'ordering': ['type', 'order', 'name'],
},
),
]

View File

@@ -0,0 +1,49 @@
# Generated by Django 5.2.7 on 2026-03-09 10:51
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0013_referenceitemmodel'),
]
operations = [
migrations.AlterField(
model_name='quickevaluationmodel',
name='body_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_body_types', to='evaluation.referenceitemmodel', verbose_name='body type'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='brand',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_brands', to='evaluation.referenceitemmodel', verbose_name='brand'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='car_position',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_positions', to='evaluation.referenceitemmodel', verbose_name='car position'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='color',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_colors', to='evaluation.referenceitemmodel', verbose_name='color'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='fuel_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_fuel_types', to='evaluation.referenceitemmodel', verbose_name='fuel type'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='marka',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_markas', to='evaluation.referenceitemmodel', verbose_name='marka'),
),
migrations.AlterField(
model_name='quickevaluationmodel',
name='state_car',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_states', to='evaluation.referenceitemmodel', verbose_name='car state'),
),
]

View File

@@ -0,0 +1,108 @@
# Generated by Django 5.2.7 on 2026-03-09 12:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0014_alter_quickevaluationmodel_body_type_and_more'),
]
operations = [
migrations.AddField(
model_name='autoevaluationmodel',
name='contract_date',
field=models.DateField(blank=True, null=True, verbose_name='contract date'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='form_ownership',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='form of ownership'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_inspection_date',
field=models.DateField(blank=True, null=True, verbose_name='object inspection date'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_location_city',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='object location city'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_location_district',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='object location district'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_location_province',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='object location province'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_owner_type',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='object owner type'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_type',
field=models.CharField(blank=True, choices=[('lightweight_auto', 'Lightweight Auto'), ('truck_car', 'Truck Car'), ('special_tech', 'Special Tech')], max_length=50, null=True, verbose_name='object type'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='property_rights',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='property rights'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='rate_date',
field=models.DateField(blank=True, null=True, verbose_name='rate date'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='rate_object_name',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='rate object name'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='rate_report_date',
field=models.DateField(blank=True, null=True, verbose_name='rate report date'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='rate_type',
field=models.IntegerField(blank=True, choices=[(1, '1-tur'), (2, '2-tur'), (3, '3-tur'), (4, '4-tur')], null=True, verbose_name='rate type'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='rating_goal',
field=models.CharField(blank=True, choices=[('sotuv', 'Sotuv'), ('kredit', 'Kredit'), ('sugurta', "Sug'urta"), ('boshqa', 'Boshqa')], max_length=50, null=True, verbose_name='rating goal'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='registration_number',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='registration number'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='status',
field=models.CharField(choices=[('yaratildi', 'Yaratildi'), ('baxolovchi_biriktirildi', 'Baholovchi biriktirildi'), ('baxolandi', 'Baholandi'), ('rad_etildi', 'Rad etildi'), ('tasdiqlandi', 'Tasdiqlandi')], default='yaratildi', max_length=50, verbose_name='status'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='tex_passport_gived_date',
field=models.DateField(blank=True, null=True, verbose_name='tech passport given date'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='tex_passport_serie_num',
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='tech passport series and number'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='value_determined',
field=models.IntegerField(blank=True, choices=[(1, '1-qiymat'), (2, '2-qiymat'), (3, '3-qiymat'), (4, '4-qiymat')], null=True, verbose_name='value determined'),
),
]

View File

@@ -0,0 +1,44 @@
# Generated by Django 5.2.7 on 2026-03-09 12:34
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0015_autoevaluationmodel_contract_date_and_more'),
]
operations = [
migrations.AlterField(
model_name='vehiclemodel',
name='body_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='vehicle_body_types', to='evaluation.referenceitemmodel', verbose_name='body type'),
),
migrations.AlterField(
model_name='vehiclemodel',
name='brand',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='vehicle_brands', to='evaluation.referenceitemmodel', verbose_name='brand'),
),
migrations.AlterField(
model_name='vehiclemodel',
name='color',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='vehicle_colors', to='evaluation.referenceitemmodel', verbose_name='color'),
),
migrations.AlterField(
model_name='vehiclemodel',
name='fuel_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='vehicle_fuel_types', to='evaluation.referenceitemmodel', verbose_name='fuel type'),
),
migrations.AlterField(
model_name='vehiclemodel',
name='model',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='vehicle_models', to='evaluation.referenceitemmodel', verbose_name='model'),
),
migrations.AlterField(
model_name='vehiclemodel',
name='position',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='vehicle_positions', to='evaluation.referenceitemmodel', verbose_name='position'),
),
]

View File

@@ -0,0 +1,159 @@
# Generated by Django 5.2.7 on 2026-03-09 12:54
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0016_alter_vehiclemodel_body_type_and_more'),
]
operations = [
migrations.AddField(
model_name='autoevaluationmodel',
name='car_brand',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='car brand'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='car_color',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='car color'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='car_dvigatel_number',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='engine number'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='car_model',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='car model'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='car_number',
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='car number'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='car_type',
field=models.IntegerField(blank=True, choices=[(1, 'Xetchbek'), (2, 'Universal')], null=True, verbose_name='car type'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='car_wheel',
field=models.IntegerField(blank=True, choices=[(1, '4x4')], null=True, verbose_name='car wheel'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='manufacture_year',
field=models.CharField(blank=True, max_length=10, null=True, verbose_name='manufacture year'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_location_covenience',
field=models.IntegerField(blank=True, choices=[(1, 'Aholi gavjum hudud'), (2, 'Bozor hududi')], null=True, verbose_name='location convenience'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_location_highways',
field=models.IntegerField(blank=True, choices=[(1, 'Tuman/Shahar markazi'), (2, 'Tuman/shahar markazidan uzoqda')], null=True, verbose_name='location highways'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_location_home',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='object location home'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_location_neighborhood',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='object location neighborhood'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_location_street',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='object location street'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_owner_individual_person_f_name',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='owner first name'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_owner_individual_person_l_name',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='owner last name'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_owner_individual_person_p_name',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='owner patronymic'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_owner_individual_person_passport_num',
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='owner passport number'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_owner_legal_entity',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='legal entity name'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='object_owner_legal_inn',
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='legal entity INN'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='tex_passport_gived_location',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='tech passport given location'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='form_ownership',
field=models.IntegerField(blank=True, choices=[(1, 'Xususiy'), (2, 'Davlat'), (3, 'AJ'), (4, 'MCHJ'), (5, 'Boshqa')], null=True, verbose_name='form of ownership'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='object_owner_type',
field=models.IntegerField(blank=True, choices=[(1, 'Jismoniy shaxs'), (2, 'Yuridik shaxs')], null=True, verbose_name='object owner type'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
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, verbose_name='object type'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='property_rights',
field=models.IntegerField(blank=True, choices=[(1, 'Doimiy egalik'), (2, 'Doimiy foydalanish'), (3, 'Vaqtinchalik foydalanish'), (4, 'Muddatli ijara'), (5, 'Umrbod meros qilib olish')], null=True, verbose_name='property rights'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='rate_type',
field=models.IntegerField(blank=True, choices=[(1, "Kredit ta'minoti sifatida garovga qo'yish"), (2, 'Sotish maqsadida bozor qiymatini aniqlash'), (3, 'Soliqqa tortish maqsadida'), (4, 'Boshqa')], null=True, verbose_name='rate type'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='rating_goal',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='rating goal'),
),
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', verbose_name='valuation'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='value_determined',
field=models.IntegerField(blank=True, choices=[(1, 'Bozor qiymati'), (2, 'Soliq maqsadlari uchun'), (3, 'Tugatish qiymati'), (4, 'Utilizatsiya qiymati')], null=True, verbose_name='value determined'),
),
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', verbose_name='vehicle'),
),
]

View File

@@ -0,0 +1,58 @@
# Generated by Django 5.2.7 on 2026-03-10 07:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0017_autoevaluationmodel_car_brand_and_more'),
]
operations = [
migrations.AddField(
model_name='autoevaluationmodel',
name='chassi',
field=models.IntegerField(blank=True, null=True, verbose_name='chassi'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='customer_inn_number',
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='customer INN number'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='location_lat',
field=models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True, verbose_name='location latitude'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='location_lng',
field=models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True, verbose_name='location longitude'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='need_delivering',
field=models.BooleanField(default=True, verbose_name='need delivering'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='owner_inn_number',
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='owner INN number'),
),
migrations.AddField(
model_name='autoevaluationmodel',
name='worked_hours',
field=models.IntegerField(blank=True, null=True, verbose_name='worked hours'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='rate_type',
field=models.CharField(blank=True, choices=[('auto', 'Automobil'), ('real_estate', "Ko'chmas mulk"), ('equipment', 'Uskuna')], max_length=50, null=True, verbose_name='rate type'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='status',
field=models.CharField(choices=[('pending', 'Kutilmoqda'), ('in_progress', 'Jarayonda'), ('completed', 'Bajarildi'), ('rejected', 'Rad etildi')], default='pending', max_length=50, verbose_name='status'),
),
]

View File

@@ -0,0 +1,51 @@
# Generated by Django 5.2.7 on 2026-03-10 08:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('evaluation', '0018_autoevaluationmodel_chassi_and_more'),
]
operations = [
migrations.RemoveField(
model_name='autoevaluationmodel',
name='chassi',
),
migrations.RemoveField(
model_name='autoevaluationmodel',
name='customer_inn_number',
),
migrations.RemoveField(
model_name='autoevaluationmodel',
name='location_lat',
),
migrations.RemoveField(
model_name='autoevaluationmodel',
name='location_lng',
),
migrations.RemoveField(
model_name='autoevaluationmodel',
name='need_delivering',
),
migrations.RemoveField(
model_name='autoevaluationmodel',
name='owner_inn_number',
),
migrations.RemoveField(
model_name='autoevaluationmodel',
name='worked_hours',
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='rate_type',
field=models.IntegerField(blank=True, choices=[(1, "Kredit ta'minoti sifatida garovga qo'yish"), (2, 'Sotish maqsadida bozor qiymatini aniqlash'), (3, 'Soliqqa tortish maqsadida'), (4, 'Boshqa')], null=True, verbose_name='rate type'),
),
migrations.AlterField(
model_name='autoevaluationmodel',
name='status',
field=models.CharField(choices=[('yaratildi', 'Yaratildi'), ('baxolovchi_biriktirildi', 'Baholovchi biriktirildi'), ('baxolandi', 'Baholandi'), ('rad_etildi', 'Rad etildi'), ('tasdiqlandi', 'Tasdiqlandi')], default='yaratildi', max_length=50, verbose_name='status'),
),
]

View File

@@ -0,0 +1,10 @@
from .auto import * # noqa
from .customer import * # noqa
from .document import * # noqa
from .movable import * # noqa
from .quick import * # noqa
from .real_estate import * # noqa
from .reference import * # noqa
from .report import * # noqa
from .valuation import * # noqa
from .vehicle import * # noqa

View File

@@ -0,0 +1,293 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_core.models import AbstractBaseModel
from model_bakery import baker
from core.apps.evaluation.choices.auto import (
AutoCarType,
AutoCarWheel,
AutoEvaluationStatus,
AutoObjectType,
FormOwnership,
LocationConvenience,
LocationHighways,
ObjectOwnerType,
PropertyRights,
RateType,
ValueDetermined,
)
from .valuation import ValuationModel
from .vehicle import VehicleModel
class AutoEvaluationModel(AbstractBaseModel):
valuation = models.OneToOneField(
ValuationModel,
on_delete=models.CASCADE,
related_name="auto_detail",
verbose_name=_("valuation"),
null=True,
blank=True,
)
vehicle = models.OneToOneField(
VehicleModel,
on_delete=models.CASCADE,
related_name="evaluation",
verbose_name=_("vehicle"),
null=True,
blank=True,
)
# ── Step 1 — Umumiy ma'lumotlar ──────────────────────────────────
registration_number = models.CharField(
verbose_name=_("registration number"),
max_length=50,
blank=True,
null=True,
)
contract_date = models.DateField(
verbose_name=_("contract date"),
blank=True,
null=True,
)
object_inspection_date = models.DateField(
verbose_name=_("object inspection date"),
blank=True,
null=True,
)
rate_date = models.DateField(
verbose_name=_("rate date"),
blank=True,
null=True,
)
rate_report_date = models.DateField(
verbose_name=_("rate report date"),
blank=True,
null=True,
)
rate_object_name = models.CharField(
verbose_name=_("rate object name"),
max_length=255,
blank=True,
null=True,
)
object_type = models.CharField(
verbose_name=_("object type"),
max_length=50,
choices=AutoObjectType.choices,
blank=True,
null=True,
)
# ── Step 2 — Shaxs ma'lumotlari ─────────────────────────────────
object_owner_type = models.IntegerField(
verbose_name=_("object owner type"),
choices=ObjectOwnerType.choices,
blank=True,
null=True,
)
object_owner_individual_person_f_name = models.CharField(
verbose_name=_("owner first name"),
max_length=100,
blank=True,
null=True,
)
object_owner_individual_person_l_name = models.CharField(
verbose_name=_("owner last name"),
max_length=100,
blank=True,
null=True,
)
object_owner_individual_person_p_name = models.CharField(
verbose_name=_("owner patronymic"),
max_length=100,
blank=True,
null=True,
)
object_owner_individual_person_passport_num = models.CharField(
verbose_name=_("owner passport number"),
max_length=20,
blank=True,
null=True,
)
object_owner_legal_entity = models.CharField(
verbose_name=_("legal entity name"),
max_length=255,
blank=True,
null=True,
)
object_owner_legal_inn = models.CharField(
verbose_name=_("legal entity INN"),
max_length=20,
blank=True,
null=True,
)
property_rights = models.IntegerField(
verbose_name=_("property rights"),
choices=PropertyRights.choices,
blank=True,
null=True,
)
form_ownership = models.IntegerField(
verbose_name=_("form of ownership"),
choices=FormOwnership.choices,
blank=True,
null=True,
)
value_determined = models.IntegerField(
verbose_name=_("value determined"),
choices=ValueDetermined.choices,
blank=True,
null=True,
)
rate_type = models.IntegerField(
verbose_name=_("rate type"),
choices=RateType.choices,
blank=True,
null=True,
)
# ── Step 3 — Manzil ma'lumotlari ────────────────────────────────
object_location_province = models.CharField(
verbose_name=_("object location province"),
max_length=100,
blank=True,
null=True,
)
object_location_district = models.CharField(
verbose_name=_("object location district"),
max_length=100,
blank=True,
null=True,
)
object_location_city = models.CharField(
verbose_name=_("object location city"),
max_length=100,
blank=True,
null=True,
)
object_location_neighborhood = models.CharField(
verbose_name=_("object location neighborhood"),
max_length=100,
blank=True,
null=True,
)
object_location_street = models.CharField(
verbose_name=_("object location street"),
max_length=100,
blank=True,
null=True,
)
object_location_home = models.CharField(
verbose_name=_("object location home"),
max_length=50,
blank=True,
null=True,
)
object_location_highways = models.IntegerField(
verbose_name=_("location highways"),
choices=LocationHighways.choices,
blank=True,
null=True,
)
object_location_covenience = models.IntegerField(
verbose_name=_("location convenience"),
choices=LocationConvenience.choices,
blank=True,
null=True,
)
# ── Step 4 — Avtomobil ma'lumotlari ─────────────────────────────
tex_passport_serie_num = models.CharField(
verbose_name=_("tech passport series and number"),
max_length=20,
blank=True,
null=True,
)
tex_passport_gived_date = models.DateField(
verbose_name=_("tech passport given date"),
blank=True,
null=True,
)
tex_passport_gived_location = models.CharField(
verbose_name=_("tech passport given location"),
max_length=255,
blank=True,
null=True,
)
car_type = models.IntegerField(
verbose_name=_("car type"),
choices=AutoCarType.choices,
blank=True,
null=True,
)
car_wheel = models.IntegerField(
verbose_name=_("car wheel"),
choices=AutoCarWheel.choices,
blank=True,
null=True,
)
car_brand = models.CharField(
verbose_name=_("car brand"),
max_length=100,
blank=True,
null=True,
)
car_model = models.CharField(
verbose_name=_("car model"),
max_length=100,
blank=True,
null=True,
)
car_number = models.CharField(
verbose_name=_("car number"),
max_length=20,
blank=True,
null=True,
)
manufacture_year = models.CharField(
verbose_name=_("manufacture year"),
max_length=10,
blank=True,
null=True,
)
car_dvigatel_number = models.CharField(
verbose_name=_("engine number"),
max_length=50,
blank=True,
null=True,
)
car_color = models.CharField(
verbose_name=_("car color"),
max_length=50,
blank=True,
null=True,
)
# ── Natija ───────────────────────────────────────────────────────
rating_goal = models.CharField(
verbose_name=_("rating goal"),
max_length=50,
blank=True,
null=True,
)
status = models.CharField(
verbose_name=_("status"),
max_length=50,
choices=AutoEvaluationStatus.choices,
default=AutoEvaluationStatus.CREATED,
)
def __str__(self):
return f"Auto Evaluation {self.registration_number or self.pk}"
@classmethod
def _baker(cls):
return baker.make(cls)
class Meta:
db_table = "AutoEvaluation"
verbose_name = _("Auto Evaluation")
verbose_name_plural = _("Auto Evaluations")

View File

@@ -0,0 +1,167 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_core.models import AbstractBaseModel
from model_bakery import baker
class CustomerTypeChoice(models.TextChoices):
LEGAL = "legal", _("Yuridik shaxs")
INDIVIDUAL = "individual", _("Jismoniy shaxs")
class CustomerModel(AbstractBaseModel):
"""Buyurtmachi — baholashga buyurtma beruvchi (yuridik yoki jismoniy shaxs)"""
customer_type = models.CharField(
verbose_name=_("customer type"),
max_length=20,
choices=CustomerTypeChoice,
)
# --- Jismoniy shaxs ma'lumotlari ---
jshshir = models.CharField(
verbose_name=_("JSHSHIR"), max_length=14, blank=True, default=""
) # Kiritiladi
passport_series = models.CharField(
verbose_name=_("passport series"), max_length=10, blank=True, default=""
) # Kiritiladi
passport_number = models.CharField(
verbose_name=_("passport number"), max_length=20, blank=True, default=""
) # Kiritiladi
first_name = models.CharField(
verbose_name=_("first name"), max_length=255, blank=True, default=""
) # 🌐 API: JSHSHIR orqali to'ladi
last_name = models.CharField(
verbose_name=_("last name"), max_length=255, blank=True, default=""
) # 🌐 API: JSHSHIR orqali to'ladi
middle_name = models.CharField(
verbose_name=_("middle name"), max_length=255, blank=True, default=""
) # 🌐 API: JSHSHIR orqali to'ladi
address = models.TextField(
verbose_name=_("address"), blank=True, default=""
) # 🌐 API: JSHSHIR orqali to'ladi
passport_issued_date = models.DateField(
verbose_name=_("passport issued date"), null=True, blank=True
) # 🌐 API
passport_issued_by = models.CharField(
verbose_name=_("passport issued by"), max_length=255, blank=True, default=""
) # 🌐 API
# --- Yuridik shaxs ma'lumotlari ---
inn = models.CharField(
verbose_name=_("INN"), max_length=20, blank=True, default=""
) # Kiritiladi
org_name = models.CharField(
verbose_name=_("organization name"), max_length=500, blank=True, default=""
) # 🌐 API: INN orqali to'ladi
org_address = models.TextField(
verbose_name=_("organization address"), blank=True, default=""
) # 🌐 API: INN orqali to'ladi
director_name = models.CharField(
verbose_name=_("director full name"), max_length=255, blank=True, default=""
) # 🌐 API: INN orqali to'ladi
mfo = models.CharField(
verbose_name=_("MFO"), max_length=10, blank=True, default=""
) # 🌐 API: INN orqali to'ladi
bank_account = models.CharField(
verbose_name=_("bank account (HISOB raqam)"), max_length=30, blank=True, default=""
) # 🌐 API: INN orqali to'ladi
certificate_file = models.FileField(
verbose_name=_("certificate file (guvohnoma)"),
upload_to="customers/certificates/",
null=True,
blank=True,
) # Yuridik shaxs guvohnomasi
def __str__(self):
if self.customer_type == CustomerTypeChoice.LEGAL:
return self.org_name or str(self.pk)
return f"{self.last_name} {self.first_name}" or str(self.pk)
@classmethod
def _baker(cls):
return baker.make(cls, customer_type=CustomerTypeChoice.INDIVIDUAL)
class Meta:
db_table = "customer"
verbose_name = _("Customer")
verbose_name_plural = _("Customers")
class PropertyOwnerModel(AbstractBaseModel):
"""Mulk egasi — agar buyurtmachi va mulk egasi boshqa-boshqa bo'lsa"""
owner_type = models.CharField(
verbose_name=_("owner type"),
max_length=20,
choices=CustomerTypeChoice,
)
# --- Jismoniy shaxs ma'lumotlari ---
jshshir = models.CharField(
verbose_name=_("JSHSHIR"), max_length=14, blank=True, default=""
)
passport_series = models.CharField(
verbose_name=_("passport series"), max_length=10, blank=True, default=""
)
passport_number = models.CharField(
verbose_name=_("passport number"), max_length=20, blank=True, default=""
)
first_name = models.CharField(
verbose_name=_("first name"), max_length=255, blank=True, default=""
) # 🌐 API
last_name = models.CharField(
verbose_name=_("last name"), max_length=255, blank=True, default=""
) # 🌐 API
middle_name = models.CharField(
verbose_name=_("middle name"), max_length=255, blank=True, default=""
) # 🌐 API
address = models.TextField(
verbose_name=_("address"), blank=True, default=""
) # 🌐 API
passport_issued_date = models.DateField(
verbose_name=_("passport issued date"), null=True, blank=True
) # 🌐 API
passport_issued_by = models.CharField(
verbose_name=_("passport issued by"), max_length=255, blank=True, default=""
) # 🌐 API
# --- Yuridik shaxs ma'lumotlari ---
inn = models.CharField(
verbose_name=_("INN"), max_length=20, blank=True, default=""
)
org_name = models.CharField(
verbose_name=_("organization name"), max_length=500, blank=True, default=""
) # 🌐 API
org_address = models.TextField(
verbose_name=_("organization address"), blank=True, default=""
) # 🌐 API
director_name = models.CharField(
verbose_name=_("director full name"), max_length=255, blank=True, default=""
) # 🌐 API
mfo = models.CharField(
verbose_name=_("MFO"), max_length=10, blank=True, default=""
) # 🌐 API
bank_account = models.CharField(
verbose_name=_("bank account (HISOB raqam)"), max_length=30, blank=True, default=""
) # 🌐 API
certificate_file = models.FileField(
verbose_name=_("certificate file (guvohnoma)"),
upload_to="property_owners/certificates/",
null=True,
blank=True,
)
def __str__(self):
if self.owner_type == CustomerTypeChoice.LEGAL:
return self.org_name or str(self.pk)
return f"{self.last_name} {self.first_name}" or str(self.pk)
@classmethod
def _baker(cls):
return baker.make(cls, owner_type=CustomerTypeChoice.INDIVIDUAL)
class Meta:
db_table = "property_owner"
verbose_name = _("Property Owner")
verbose_name_plural = _("Property Owners")

View File

@@ -0,0 +1,56 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_core.models import AbstractBaseModel
from model_bakery import baker
from .valuation import ValuationModel
from core.apps.evaluation.choices.document import DocumentType
class ValuationDocumentModel(AbstractBaseModel):
valuation = models.ForeignKey(
ValuationModel,
on_delete=models.CASCADE,
related_name="documents",
verbose_name=_("valuation"),
)
document_type = models.CharField(
verbose_name=_("document type"),
max_length=50,
choices=DocumentType.choices,
default=DocumentType.OTHER,
)
title = models.CharField(
verbose_name=_("title"),
max_length=255,
blank=True,
)
file = models.FileField(
verbose_name=_("file"),
upload_to="evaluation/documents/%Y/%m/",
)
uploaded_by = models.ForeignKey(
"accounts.User",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="uploaded_documents",
verbose_name=_("uploaded by"),
)
description = models.TextField(
verbose_name=_("description"),
blank=True,
)
def __str__(self):
return f"{self.get_document_type_display()}{self.valuation}"
@classmethod
def _baker(cls):
return baker.make(cls)
class Meta:
db_table = "ValuationDocument"
verbose_name = _("Valuation Document")
verbose_name_plural = _("Valuation Documents")
ordering = ["-created_at"]

View File

@@ -0,0 +1,54 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_core.models import AbstractBaseModel
from model_bakery import baker
from .valuation import ValuationModel
from core.apps.evaluation.choices.movable import (
MovablePropertyCategory,
MovablePropertyCondition,
)
class MovablePropertyEvaluationModel(AbstractBaseModel):
valuation = models.OneToOneField(
ValuationModel,
on_delete=models.CASCADE,
related_name="movable_property_detail",
verbose_name=_("valuation"),
)
property_name = models.CharField(verbose_name=_("property name"), max_length=255)
property_category = models.CharField(
verbose_name=_("property category"),
max_length=50,
choices=MovablePropertyCategory.choices,
default=MovablePropertyCategory.OTHER,
)
serial_number = models.CharField(
verbose_name=_("serial number"), max_length=100, blank=True, null=True
)
manufacture_year = models.IntegerField(
verbose_name=_("manufacture year"), blank=True, null=True
)
condition = models.CharField(
verbose_name=_("condition"),
max_length=50,
choices=MovablePropertyCondition.choices,
blank=True,
null=True,
)
quantity = models.IntegerField(verbose_name=_("quantity"), default=1)
def __str__(self):
return f"Movable Property Evaluation: {self.property_name} ({self.valuation})"
@classmethod
def _baker(cls):
return baker.make(cls)
class Meta:
db_table = "MovablePropertyEvaluation"
verbose_name = _("Movable Property Evaluation")
verbose_name_plural = _("Movable Property Evaluations")

View File

@@ -0,0 +1,152 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_core.models import AbstractBaseModel
from model_bakery import baker
from core.apps.evaluation.choices.quick import CarType, QuickEvaluationStatus
class QuickEvaluationModel(AbstractBaseModel):
created_by = models.ForeignKey(
"accounts.User",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="quick_evaluations",
verbose_name=_("created by"),
)
# Tex passport
tex_passport_serie_num = models.CharField(
verbose_name=_("tech passport series and number"),
max_length=20,
blank=True,
null=True,
)
tech_passport_issued_date = models.DateField(
verbose_name=_("tech passport issued date"),
blank=True,
null=True,
)
tech_passport_issued_place = models.CharField(
verbose_name=_("tech passport issued place"),
max_length=255,
blank=True,
null=True,
)
tex_passport_file = models.FileField(
verbose_name=_("tech passport file"),
upload_to="quick_evaluation/tech_passports/%Y/%m/",
blank=True,
null=True,
)
# Car info
car_type = models.CharField(
verbose_name=_("car type"),
max_length=50,
choices=CarType.choices,
blank=True,
null=True,
)
brand = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="quick_eval_brands",
verbose_name=_("brand"),
)
marka = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="quick_eval_markas",
verbose_name=_("marka"),
)
car_position = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="quick_eval_positions",
verbose_name=_("car position"),
)
distance_covered = models.IntegerField(
verbose_name=_("distance covered (km)"),
blank=True,
null=True,
)
body_type = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="quick_eval_body_types",
verbose_name=_("body type"),
)
vin_number = models.CharField(
verbose_name=_("VIN number"), max_length=50, blank=True, null=True
)
car_number = models.CharField(
verbose_name=_("car number"), max_length=20, blank=True, null=True
)
car_manufactured_date = models.IntegerField(
verbose_name=_("manufacture year"), blank=True, null=True
)
engine_number = models.CharField(
verbose_name=_("engine number"), max_length=50, blank=True, null=True
)
color = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="quick_eval_colors",
verbose_name=_("color"),
)
fuel_type = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="quick_eval_fuel_types",
verbose_name=_("fuel type"),
)
state_car = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="quick_eval_states",
verbose_name=_("car state"),
)
# Result
estimated_price = models.DecimalField(
verbose_name=_("estimated price"),
max_digits=15,
decimal_places=2,
blank=True,
null=True,
)
status = models.CharField(
verbose_name=_("status"),
max_length=50,
choices=QuickEvaluationStatus.choices,
default=QuickEvaluationStatus.CREATED,
)
def __str__(self):
return f"Quick Evaluation {self.pk} by {self.created_by}"
@classmethod
def _baker(cls):
return baker.make(cls)
class Meta:
db_table = "QuickEvaluation"
verbose_name = _("Quick Evaluation")
verbose_name_plural = _("Quick Evaluations")

View File

@@ -0,0 +1,68 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_core.models import AbstractBaseModel
from model_bakery import baker
from .valuation import ValuationModel
from core.apps.evaluation.choices.real_estate import PropertyType, RealEstateCondition
class RealEstateEvaluationModel(AbstractBaseModel):
valuation = models.OneToOneField(
"evaluation.ValuationModel",
on_delete=models.CASCADE,
related_name="real_estate_detail",
verbose_name=_("valuation"),
)
property_type = models.CharField(
verbose_name=_("property type"),
max_length=50,
choices=PropertyType.choices,
default=PropertyType.APARTMENT,
)
address = models.TextField(verbose_name=_("address"))
cadastral_number = models.CharField(
verbose_name=_("cadastral number"), max_length=50, blank=True, null=True
)
total_area = models.DecimalField(
verbose_name=_("total area"), max_digits=12, decimal_places=2
)
living_area = models.DecimalField(
verbose_name=_("living area"),
max_digits=12,
decimal_places=2,
blank=True,
null=True,
)
floor = models.IntegerField(verbose_name=_("floor"), blank=True, null=True)
total_floors = models.IntegerField(
verbose_name=_("total floors"), blank=True, null=True
)
rooms_count = models.IntegerField(
verbose_name=_("rooms count"), blank=True, null=True
)
build_year = models.IntegerField(verbose_name=_("build year"), blank=True, null=True)
condition = models.CharField(
verbose_name=_("condition"),
max_length=50,
choices=RealEstateCondition.choices,
blank=True,
null=True,
)
has_renovation = models.BooleanField(verbose_name=_("has renovation"), default=False)
def __str__(self):
return f"Real Estate Evaluation for {self.valuation}"
@classmethod
def _baker(cls):
return baker.make(cls)
class Meta:
db_table = "RealEstateEvaluation"
verbose_name = _("Real Estate Evaluation")
verbose_name_plural = _("Real Estate Evaluations")

View File

@@ -0,0 +1,38 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_core.models import AbstractBaseModel
from model_bakery import baker
from core.apps.evaluation.choices.reference import ReferenceType
class ReferenceitemModel(AbstractBaseModel):
type = models.CharField(
verbose_name=_("type"),
max_length=50,
choices=ReferenceType.choices,
)
name = models.CharField(verbose_name=_("name"), max_length=255)
parent = models.ForeignKey(
"self",
on_delete=models.CASCADE,
null=True,
blank=True,
related_name="children",
verbose_name=_("parent"),
)
order = models.IntegerField(verbose_name=_("order"), default=0)
is_active = models.BooleanField(verbose_name=_("is active"), default=True)
def __str__(self):
return f"{self.get_type_display()}: {self.name}"
@classmethod
def _baker(cls):
return baker.make(cls)
class Meta:
db_table = "ReferenceItem"
verbose_name = _("Reference Item")
verbose_name_plural = _("Reference Items")
ordering = ["type", "order", "name"]

View File

@@ -0,0 +1,48 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_core.models import AbstractBaseModel
from model_bakery import baker
from .valuation import ValuationModel
class EvaluationReportModel(AbstractBaseModel):
valuation = models.OneToOneField(
ValuationModel,
on_delete=models.CASCADE,
related_name="report",
verbose_name=_("valuation"),
)
evaluator = models.ForeignKey(
"accounts.User",
on_delete=models.PROTECT,
related_name="reports",
verbose_name=_("evaluator"),
)
report_number = models.CharField(
verbose_name=_("report number"), max_length=100, unique=True
)
final_value = models.DecimalField(
verbose_name=_("final value"), max_digits=15, decimal_places=2
)
report_file = models.FileField(
verbose_name=_("report file"), upload_to="evaluation/reports/", blank=True, null=True
)
conclusion_text = models.TextField(verbose_name=_("conclusion text"), blank=True)
approved_at = models.DateTimeField(
verbose_name=_("approved at"), blank=True, null=True
)
def __str__(self):
return f"Report #{self.report_number} for {self.valuation}"
@classmethod
def _baker(cls):
return baker.make(cls)
class Meta:
db_table = "EvaluationReport"
verbose_name = _("Evaluation Report")
verbose_name_plural = _("Evaluation Reports")

View File

@@ -0,0 +1,127 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_core.models import AbstractBaseModel
from model_bakery import baker
from core.apps.evaluation.choices.valuation import (
EvaluationPurpose,
EvaluationType,
ValuationStatus,
PaymentStatus,
)
from .customer import CustomerModel, PropertyOwnerModel
class ValuationModel(AbstractBaseModel):
# 📋 Asosiy ma'lumotlar
conclusion_number = models.CharField(
verbose_name=_("conclusion number"),
max_length=50,
unique=True,
blank=True,
null=True,
)
evaluation_purpose = models.CharField(
verbose_name=_("evaluation purpose"),
max_length=50,
choices=EvaluationPurpose.choices,
default=EvaluationPurpose.SALE,
)
evaluation_type = models.CharField(
verbose_name=_("evaluation type"),
max_length=50,
choices=EvaluationType.choices,
)
evaluation_subtype = models.CharField(
verbose_name=_("evaluation subtype"),
max_length=100,
blank=True,
null=True,
)
status = models.CharField(
verbose_name=_("status"),
max_length=20,
choices=ValuationStatus.choices,
default=ValuationStatus.DRAFT,
)
# 👥 Bog'lanishlar
customer = models.ForeignKey(
CustomerModel,
on_delete=models.PROTECT,
related_name="valuations",
verbose_name=_("customer"),
)
property_owner = models.ForeignKey(
PropertyOwnerModel,
on_delete=models.PROTECT,
related_name="valuations",
verbose_name=_("property owner"),
null=True,
blank=True,
help_text=_("Keep empty if customer is the owner"),
)
created_by = models.ForeignKey(
"accounts.User",
on_delete=models.PROTECT,
related_name="created_valuations",
verbose_name=_("created by"),
)
assigned_to = models.ForeignKey(
"accounts.User",
on_delete=models.SET_NULL,
related_name="assigned_valuations",
verbose_name=_("assigned to"),
null=True,
blank=True,
)
# 💰 Narx va To'lov
estimated_price = models.DecimalField(
verbose_name=_("estimated price"),
max_digits=15,
decimal_places=2,
null=True,
blank=True,
)
final_price = models.DecimalField(
verbose_name=_("final price"),
max_digits=15,
decimal_places=2,
null=True,
blank=True,
)
payment_status = models.CharField(
verbose_name=_("payment status"),
max_length=20,
choices=PaymentStatus.choices,
default=PaymentStatus.UNPAID,
)
# 🚚 Yetkazib berish
is_courier_delivery = models.BooleanField(
verbose_name=_("courier delivery"), default=False
)
courier_extra_amount = models.DecimalField(
verbose_name=_("courier extra amount"),
max_digits=12,
decimal_places=2,
default=0,
)
# 📝 Izohlar
notes = models.TextField(verbose_name=_("notes"), blank=True, null=True)
def __str__(self):
return f"Valuation {self.conclusion_number} - {self.customer}"
@classmethod
def _baker(cls):
return baker.make(cls)
class Meta:
db_table = "Valuation"
verbose_name = _("Valuation")
verbose_name_plural = _("Valuations")

View File

@@ -0,0 +1,110 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_core.models import AbstractBaseModel
from model_bakery import baker
from core.apps.evaluation.choices.vehicle import VehicleCondition
class VehicleModel(AbstractBaseModel):
# 🌐 Texnik passport ma'lumotlari (API orqali olinadi)
tech_passport_series = models.CharField(
verbose_name=_("tech passport series"), max_length=10, blank=True, null=True
)
tech_passport_number = models.CharField(
verbose_name=_("tech passport number"), max_length=20, blank=True, null=True
)
tech_passport_issued_date = models.DateField(
verbose_name=_("tech passport issued date"), blank=True, null=True
)
tech_passport_issued_by = models.CharField(
verbose_name=_("tech passport issued by"), max_length=255, blank=True, null=True
)
license_plate = models.CharField(
verbose_name=_("license plate"), max_length=20, blank=True, null=True
)
brand = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="vehicle_brands",
verbose_name=_("brand"),
)
model = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="vehicle_models",
verbose_name=_("model"),
)
manufacture_year = models.IntegerField(
verbose_name=_("manufacture year"), blank=True, null=True
)
vin_number = models.CharField(
verbose_name=_("VIN number"), max_length=25, blank=True, null=True
)
engine_number = models.CharField(
verbose_name=_("engine number"), max_length=50, blank=True, null=True
)
color = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="vehicle_colors",
verbose_name=_("color"),
)
# 🛠 Texnik holati
mileage = models.IntegerField(
verbose_name=_("mileage"), blank=True, null=True, help_text=_("Distance in km")
)
fuel_type = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="vehicle_fuel_types",
verbose_name=_("fuel type"),
)
body_type = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="vehicle_body_types",
verbose_name=_("body type"),
)
condition = models.CharField(
verbose_name=_("condition"),
max_length=20,
choices=VehicleCondition.choices,
blank=True,
null=True,
)
position = models.ForeignKey(
"evaluation.ReferenceitemModel",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="vehicle_positions",
verbose_name=_("position"),
)
def __str__(self):
brand_name = self.brand.name if self.brand else ""
model_name = self.model.name if self.model else ""
return f"{brand_name} {model_name} ({self.license_plate})"
@classmethod
def _baker(cls):
return baker.make(cls)
class Meta:
db_table = "Vehicle"
verbose_name = _("Vehicle")
verbose_name_plural = _("Vehicles")

View File

@@ -0,0 +1,10 @@
from .auto import * # noqa
from .customer import * # noqa
from .document import * # noqa
from .movable import * # noqa
from .quick import * # noqa
from .real_estate import * # noqa
from .reference import * # noqa
from .report import * # noqa
from .valuation import * # noqa
from .vehicle import * # noqa

View File

@@ -0,0 +1,12 @@
from rest_framework import permissions
class AutoevaluationPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True

View File

@@ -0,0 +1,23 @@
from rest_framework import permissions
class CustomerPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True
class PropertyownerPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True

View File

@@ -0,0 +1,12 @@
from rest_framework import permissions
class ValuationdocumentPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True

View File

@@ -0,0 +1,12 @@
from rest_framework import permissions
class MovablepropertyevaluationPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True

View File

@@ -0,0 +1,12 @@
from rest_framework import permissions
class QuickevaluationPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True

View File

@@ -0,0 +1,12 @@
from rest_framework import permissions
class RealestateevaluationPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True

View File

@@ -0,0 +1,12 @@
from rest_framework import permissions
class ReferenceitemPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True

View File

@@ -0,0 +1,12 @@
from rest_framework import permissions
class EvaluationreportPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True

View File

@@ -0,0 +1,12 @@
from rest_framework import permissions
class ValuationPermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True

View File

@@ -0,0 +1,12 @@
from rest_framework import permissions
class VehiclePermission(permissions.BasePermission):
def __init__(self) -> None: ...
def __call__(self, *args, **kwargs):
return self
def has_permission(self, request, view):
return True

View File

@@ -0,0 +1,10 @@
from .auto import * # noqa
from .customer import * # noqa
from .document import * # noqa
from .movable import * # noqa
from .quick import * # noqa
from .real_estate import * # noqa
from .reference import * # noqa
from .report import * # noqa
from .valuation import * # noqa
from .vehicle import * # noqa

Some files were not shown because too many files have changed in this diff Show More