first commit
This commit is contained in:
commit
3e4574dcdd
163 files changed
+3559
No files matched your search
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1,10 @@
|
||||
from django.contrib import admin
|
||||
from .models import City as CityModel
|
||||
# Register your models here.
|
||||
|
||||
|
||||
@admin.register(CityModel)
|
||||
class CityAdmin(admin.ModelAdmin):
|
||||
list_display = ['name', 'is_ostan', 'ostan', 'pv_id']
|
||||
search_fields = ['name',]
|
||||
list_filter = ['name', 'is_ostan', 'ostan',]
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class AppsettingConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.appsetting'
|
||||
@@ -0,0 +1,30 @@
|
||||
# Generated by Django 4.2.1 on 2024-03-27 13:43
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='City',
|
||||
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(blank=True, max_length=30, null=True)),
|
||||
('is_ostan', models.BooleanField(default=False)),
|
||||
('pv_id', models.PositiveSmallIntegerField(blank=True, null=True)),
|
||||
('ostan', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='appsetting.city')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,13 @@
|
||||
from django.db import models
|
||||
from utils.base_model import BaseModel
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class City(BaseModel):
|
||||
name = models.CharField(max_length=30, null=True, blank=True)
|
||||
is_ostan = models.BooleanField(default=False, null=False, blank=False)
|
||||
ostan = models.ForeignKey('self', models.CASCADE, null=True, blank=True)
|
||||
pv_id = models.PositiveSmallIntegerField(null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.name)
|
||||
@@ -0,0 +1,13 @@
|
||||
from apps.appsetting.models import City
|
||||
from django.core.cache import cache
|
||||
|
||||
|
||||
def get_city_list():
|
||||
city = cache.get('city')
|
||||
|
||||
if city is None:
|
||||
city = City.objects.all()
|
||||
# 75 hour cache
|
||||
cache.set('city', city, 60 * 60 * 72)
|
||||
|
||||
return city
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,5 @@
|
||||
from django.urls import path
|
||||
from apps.appsetting.views import CityListView
|
||||
urlpatterns = [
|
||||
path('citys/', CityListView.as_view(), name='citys'),
|
||||
]
|
||||
@@ -0,0 +1,70 @@
|
||||
from django.shortcuts import render
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import serializers
|
||||
import pandas as pd
|
||||
from apps.appsetting.models import City as CityModel
|
||||
from apps.appsetting.selector import get_city_list
|
||||
# Create your views here.
|
||||
|
||||
|
||||
class CityListView(APIView):
|
||||
class OutputSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = CityModel
|
||||
fields = '__all__'
|
||||
|
||||
def get(self, request):
|
||||
city_list = get_city_list()
|
||||
output = self.OutputSerializer(city_list, many=True)
|
||||
return Response(data=output.data)
|
||||
|
||||
|
||||
class ImportExcelOstanView(APIView):
|
||||
|
||||
def get(self, request):
|
||||
|
||||
df = pd.read_excel('ostan.xlsx')
|
||||
for index, row in df.iterrows():
|
||||
ostan_name = row['name']
|
||||
pv_id = row['pv_id']
|
||||
|
||||
try:
|
||||
ostan = CityModel.objects.filter(pv_id=pv_id, is_ostan=True).exists()
|
||||
except Exception as exp:
|
||||
print(ostan_name)
|
||||
print(pv_id)
|
||||
|
||||
if not ostan:
|
||||
ostan_obj = CityModel()
|
||||
ostan_obj.name = ostan_name
|
||||
ostan_obj.pv_id = pv_id
|
||||
ostan_obj.is_ostan = True
|
||||
ostan_obj.save()
|
||||
|
||||
return Response(data={"result": 'ok'})
|
||||
|
||||
|
||||
class ImportExcelCitysView(APIView):
|
||||
|
||||
def get(self, request):
|
||||
|
||||
|
||||
df = pd.read_excel('cities.xlsx')
|
||||
for index, row in df.iterrows():
|
||||
city_name = row['name']
|
||||
pv_id = row['province_id']
|
||||
|
||||
try:
|
||||
ostan = CityModel.objects.get(pv_id=pv_id, is_ostan=True)
|
||||
except Exception as exp:
|
||||
print(city_name)
|
||||
print(pv_id)
|
||||
|
||||
city_obj = CityModel()
|
||||
city_obj.name = city_name
|
||||
city_obj.is_ostan = False
|
||||
city_obj.ostan = ostan
|
||||
city_obj.save()
|
||||
|
||||
return Response(data={"result": 'ok'})
|
||||
Whitespace-only changes.
@@ -0,0 +1,10 @@
|
||||
from django.contrib import admin
|
||||
from import_export.admin import ImportExportModelAdmin
|
||||
from .models import CUser
|
||||
# Register your models here.
|
||||
|
||||
|
||||
@admin.register(CUser)
|
||||
class CUserAdmin(ImportExportModelAdmin):
|
||||
list_filter = ['step', 'type']
|
||||
search_fields = ['username', 'mobile', 'name_family', 'name_family']
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class CuserConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.cuser'
|
||||
@@ -0,0 +1,40 @@
|
||||
# Generated by Django 4.2.1 on 2024-03-27 10:12
|
||||
|
||||
from django.db import migrations, models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CUser',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('username', models.CharField(max_length=50, unique=True)),
|
||||
('mobile', models.PositiveBigIntegerField(unique=True)),
|
||||
('name_family', models.CharField(blank=True, max_length=50, null=True)),
|
||||
('is_active', models.BooleanField(default=False)),
|
||||
('is_staff', models.BooleanField(default=False)),
|
||||
('is_superuser', models.BooleanField(default=False)),
|
||||
('step', models.CharField(choices=[('1', '1-register'), ('2', '2-profileOk')], default='1')),
|
||||
('type', models.CharField(choices=[('MO', 'mojri'), ('OP', 'operator')], default='MO')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
|
||||
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
|
||||
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.1 on 2024-03-27 12:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cuser', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cuser',
|
||||
name='mobile',
|
||||
field=models.PositiveBigIntegerField(blank=True, null=True, unique=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-20 11:08
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cuser', '0002_alter_cuser_mobile'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='cuser',
|
||||
name='mojri_status',
|
||||
field=models.CharField(blank=True, choices=[('WT', 'waiting'), ('AP', 'approv'), ('RJ', 'reject')], default='WT', null=True),
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,63 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
|
||||
from utils.base_model import BaseModel
|
||||
import uuid
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class CUserManager(BaseUserManager):
|
||||
def create_user(self, username, password, **extra_fields):
|
||||
if not username:
|
||||
raise ValueError("Please Enter username")
|
||||
user = self.model(username=username, **extra_fields)
|
||||
user.set_password(password)
|
||||
user.save()
|
||||
return user
|
||||
|
||||
def create_superuser(self, username, password, **extra_fields):
|
||||
extra_fields.setdefault('is_staff', True)
|
||||
extra_fields.setdefault('is_superuser', True)
|
||||
extra_fields.setdefault('is_active', True)
|
||||
|
||||
return self.create_user(username, password, **extra_fields)
|
||||
|
||||
|
||||
class CUser(BaseModel, AbstractBaseUser, PermissionsMixin):
|
||||
|
||||
STEP_CHOICES = [
|
||||
("1", "1-register"),
|
||||
("2", "2-profileOk")
|
||||
]
|
||||
|
||||
TYPE_CHOICES = [
|
||||
("MO", "mojri"),
|
||||
("OP", "operator")
|
||||
]
|
||||
|
||||
STATUS_CHOICES = [
|
||||
("WT", "waiting"),
|
||||
("AP", "approv"),
|
||||
("RJ", "reject"),
|
||||
]
|
||||
|
||||
username = models.CharField(max_length=50, null=False, blank=False, unique=True)
|
||||
mobile = models.PositiveBigIntegerField(null=True, blank=True, unique=True)
|
||||
name_family = models.CharField(max_length=50, null=True, blank=True)
|
||||
is_active = models.BooleanField(default=False)
|
||||
is_staff = models.BooleanField(default=False)
|
||||
is_superuser = models.BooleanField(default=False)
|
||||
step = models.CharField(default='1', null=False, blank=False, choices=STEP_CHOICES)
|
||||
type = models.CharField(default='MO', null=False, blank=False, choices=TYPE_CHOICES)
|
||||
mojri_status = models.CharField(default='WT', null=True, blank=True, choices=STATUS_CHOICES)
|
||||
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
||||
|
||||
USERNAME_FIELD = 'username'
|
||||
|
||||
objects = CUserManager()
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.name_family} - {self.username} - {self.mobile} - {self.type}'
|
||||
|
||||
class Meta:
|
||||
ordering = ['-created_at']
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.urls import path
|
||||
from apps.cuser.views import MojriInfoApiview
|
||||
|
||||
urlpatterns = [
|
||||
path('info/', MojriInfoApiview.as_view(), name='mojri-info'),
|
||||
]
|
||||
@@ -0,0 +1,4 @@
|
||||
from django.urls import path
|
||||
|
||||
urlpatterns = [
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,78 @@
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from django.contrib.auth import get_user_model
|
||||
from apps.cuser.models import CUser as CUserModel
|
||||
from apps.project.models import Project as ProjectModel
|
||||
from rest_framework import serializers
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from rest_framework.generics import ListAPIView
|
||||
from utils.standard_pagination import StandardPagination
|
||||
from utils.tools.inline_serializer import inline_serializer
|
||||
from apps.emtiyazat.selector import get_emtiyaz_mojri
|
||||
#get user model
|
||||
|
||||
CUserModel2 = get_user_model()
|
||||
|
||||
|
||||
class MojriInfoApiview(APIView):
|
||||
permission_classes = (IsAuthenticated, )
|
||||
|
||||
def get(self, request):
|
||||
|
||||
user_project_count = ProjectModel.objects.filter(cuser=request.user).count()
|
||||
name_family = request.user.name_family
|
||||
step = request.user.step
|
||||
|
||||
if request.user.user_profile.ax_mojri:
|
||||
image = request.user.user_profile.ax_mojri.url
|
||||
else:
|
||||
image = '/media/media/app/usericon.jpg'
|
||||
|
||||
emtiyaz = get_emtiyaz_mojri(cuser=request.user)
|
||||
|
||||
output = {
|
||||
'project_count': user_project_count,
|
||||
'name_family': name_family,
|
||||
'emtiyaz': emtiyaz,
|
||||
'step': step,
|
||||
'image': image
|
||||
}
|
||||
|
||||
return Response(output, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class ListMojrian(ListAPIView):
|
||||
|
||||
class OutputSerializer(serializers.ModelSerializer):
|
||||
|
||||
user_profile = inline_serializer(many=False, fields={
|
||||
'codemeli': serializers.IntegerField(),
|
||||
'city': inline_serializer(many=False, fields={
|
||||
'id': serializers.IntegerField(),
|
||||
'name': serializers.CharField(),
|
||||
'ostan': inline_serializer(many=False, fields={
|
||||
'id': serializers.IntegerField(),
|
||||
'name': serializers.CharField(),
|
||||
})
|
||||
}),
|
||||
'address': serializers.CharField(),
|
||||
'codeposti': serializers.IntegerField(),
|
||||
'ax_mojri': serializers.CharField(),
|
||||
'ax_meli': serializers.CharField(),
|
||||
'ax_fani': serializers.CharField(),
|
||||
'ax_sayer': serializers.CharField(),
|
||||
|
||||
})
|
||||
|
||||
class Meta:
|
||||
model = CUserModel2
|
||||
fields = ('id', 'name_family', 'mobile', 'uuid', 'user_profile')
|
||||
|
||||
permission_classes = (IsAuthenticated,)
|
||||
serializer_class = OutputSerializer
|
||||
pagination_class = StandardPagination
|
||||
|
||||
def get_queryset(self):
|
||||
mojri_status = self.request.query_params.get('status', 'WT')
|
||||
return CUserModel2.objects.filter(type='MO', is_superuser=False, mojri_status=mojri_status)
|
||||
Whitespace-only changes.
@@ -0,0 +1,14 @@
|
||||
from django.contrib import admin
|
||||
from .models import DgCode as DgCodeModel, DgCategory as DgCategoryModel
|
||||
# Register your models here.
|
||||
|
||||
|
||||
@admin.register(DgCategoryModel)
|
||||
class DgCategoryModelAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
|
||||
@admin.register(DgCodeModel)
|
||||
class DgCodeModelAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class DgcodeConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.dgcode'
|
||||
@@ -0,0 +1,48 @@
|
||||
# Generated by Django 4.2.1 on 2024-03-27 14:54
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='DgCategory',
|
||||
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(blank=True, max_length=30, null=True)),
|
||||
('desc', models.CharField(blank=True, max_length=30, null=True)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DgCode',
|
||||
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)),
|
||||
('code', models.CharField(max_length=30)),
|
||||
('is_used', models.BooleanField(default=False)),
|
||||
('buy_price', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('desc', models.CharField(blank=True, max_length=30, null=True)),
|
||||
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dgcode.dgcategory')),
|
||||
('for_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,26 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db import models
|
||||
from utils.base_model import BaseModel
|
||||
# Create your models here.
|
||||
CUserModel = get_user_model()
|
||||
|
||||
|
||||
class DgCategory(BaseModel):
|
||||
name = models.CharField(max_length=30, null=True, blank=True)
|
||||
desc = models.CharField(max_length=30, null=True, blank=True)
|
||||
is_active = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.name)
|
||||
|
||||
|
||||
class DgCode(BaseModel):
|
||||
category = models.ForeignKey(DgCategory, on_delete=models.CASCADE, null=False, blank=False)
|
||||
code = models.CharField(max_length=30, null=False, blank=False)
|
||||
is_used = models.BooleanField(default=False, null=False, blank=False)
|
||||
buy_price = models.PositiveIntegerField(null=True, blank=True)
|
||||
desc = models.CharField(max_length=30, null=True, blank=True)
|
||||
for_user = models.ForeignKey(CUserModel, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.category.name} - {self.code}'
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
Whitespace-only changes.
@@ -0,0 +1,13 @@
|
||||
from django.contrib import admin
|
||||
from apps.emtiyazat.models import Emtiyazat as EmtiyazatModel, ArzeshEmtiyaz as ArzeshEmtiyazModel
|
||||
# Register your models here.
|
||||
|
||||
|
||||
@admin.register(EmtiyazatModel)
|
||||
class EmtiyazatAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
|
||||
@admin.register(ArzeshEmtiyazModel)
|
||||
class ArzeshEmtiyazAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class EmtiyazatConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.emtiyazat'
|
||||
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-17 11:30
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Emtiyazat',
|
||||
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)),
|
||||
('credit', models.IntegerField(blank=True, default=None, null=True)),
|
||||
('debit', models.IntegerField(blank=True, default=None, null=True)),
|
||||
('desc', models.TextField(blank=True, default=None, null=True)),
|
||||
('cuser', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='emtiyazat', to=settings.AUTH_USER_MODEL)),
|
||||
('operator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='emtiyazat_operator', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-18 07:36
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('project', '0010_project_emtiyaz'),
|
||||
('emtiyazat', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='emtiyazat',
|
||||
name='project',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='emtiyaz_project', to='project.project'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-28 07:35
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('emtiyazat', '0002_emtiyazat_project'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='emtiyazat',
|
||||
options={'ordering': ['-created_at']},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 4.2.1 on 2024-05-02 09:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('emtiyazat', '0003_alter_emtiyazat_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ArzeshEmtiyaz',
|
||||
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)),
|
||||
('price', models.IntegerField()),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,26 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db import models
|
||||
from utils.base_model import BaseModel
|
||||
from apps.project.models import Project as ProjectModel
|
||||
# Create your models here.
|
||||
|
||||
|
||||
CUser = get_user_model()
|
||||
|
||||
|
||||
class ArzeshEmtiyaz(BaseModel):
|
||||
price = models.IntegerField(null=False, blank=False)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.price}'
|
||||
|
||||
class Emtiyazat(BaseModel):
|
||||
cuser = models.ForeignKey(CUser, on_delete=models.CASCADE, related_name='emtiyazat')
|
||||
credit = models.IntegerField(null=True, blank=True, default=None)
|
||||
debit = models.IntegerField(null=True, blank=True, default=None)
|
||||
desc = models.TextField(null=True, blank=True, default=None)
|
||||
project = models.ForeignKey(ProjectModel, on_delete=models.CASCADE, related_name='emtiyaz_project', null=True, blank=True)
|
||||
operator = models.ForeignKey(CUser, on_delete=models.CASCADE, related_name='emtiyazat_operator')
|
||||
|
||||
class Meta:
|
||||
ordering = ['-created_at']
|
||||
@@ -0,0 +1,20 @@
|
||||
from django.db.models import Sum
|
||||
|
||||
from apps.emtiyazat.models import Emtiyazat as EmtiyazatModel, ArzeshEmtiyaz as ArzeshEmtiyazModel
|
||||
|
||||
|
||||
def get_arzesh_emtiyaz():
|
||||
arzesh_obj = ArzeshEmtiyazModel.objects.filter().last()
|
||||
return arzesh_obj.price
|
||||
|
||||
|
||||
def get_emtiyaz_mojri(cuser) -> int:
|
||||
sum_credit = EmtiyazatModel.objects.filter(cuser=cuser).aggregate(Sum('credit'))
|
||||
sum_debit = EmtiyazatModel.objects.filter(cuser=cuser).aggregate(Sum('debit'))
|
||||
|
||||
if sum_credit['credit__sum'] is None:
|
||||
sum_credit['credit__sum'] = 0
|
||||
if sum_debit['debit__sum'] is None:
|
||||
sum_debit['debit__sum'] = 0
|
||||
|
||||
return sum_credit['credit__sum'] - sum_debit['debit__sum']
|
||||
@@ -0,0 +1,31 @@
|
||||
from apps.emtiyazat.models import Emtiyazat as EmtiyazatModel
|
||||
from apps.project.models import Project as ProjectModel
|
||||
from rest_framework.validators import ValidationError
|
||||
from utils.services.sms_task import task_send_sms
|
||||
|
||||
def add_project_emtiyaz(credit: int, project_id: int, op_user):
|
||||
try:
|
||||
project = ProjectModel.objects.get(id=project_id)
|
||||
if not project.emtiyaz and project.status == 'waiting':
|
||||
ProjectModel.objects.filter(id=project_id).update(emtiyaz=credit, status='approved')
|
||||
desc = f'بابت پروژه: {project.address}'
|
||||
emtiyaz = EmtiyazatModel.objects.create(credit=credit, desc=desc,
|
||||
cuser=project.cuser, operator=op_user, project=project)
|
||||
|
||||
message = f'پروژه شما تایید و {credit} امتیاز به پروفایل شما اضافه شد '
|
||||
task_send_sms.delay(message=message, mobile=str(project.cuser.mobile))
|
||||
|
||||
return emtiyaz
|
||||
except Exception as exp:
|
||||
raise ValidationError(f'Error on add emtiyaz {exp}')
|
||||
|
||||
|
||||
def decrease_emtiyaz(debit: int, desc: str, cuser):
|
||||
emtiyaz = EmtiyazatModel.objects.create(
|
||||
debit=debit,
|
||||
desc=desc,
|
||||
cuser=cuser,
|
||||
operator=cuser
|
||||
)
|
||||
return emtiyaz
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
from django.test import TestCase
|
||||
from rest_framework.test import APITestCase
|
||||
# Create your tests here.
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
from django.urls import path
|
||||
from apps.emtiyazat.views import ListEmtiyazatApiview, RetrieveArzeshEmtiyaz
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('list/', ListEmtiyazatApiview.as_view(), name='list-emtiyazat'),
|
||||
path('arzesh/', RetrieveArzeshEmtiyaz.as_view(), name='arzesh-emtiyaz'),
|
||||
]
|
||||
@@ -0,0 +1,38 @@
|
||||
from django.shortcuts import render
|
||||
from rest_framework import response
|
||||
from rest_framework import serializers
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.generics import ListAPIView
|
||||
from apps.emtiyazat.models import Emtiyazat as EmtiyazatModel
|
||||
from utils.standard_pagination import StandardPagination
|
||||
from utils.tools.inline_serializer import inline_serializer
|
||||
from apps.emtiyazat.selector import get_arzesh_emtiyaz
|
||||
from rest_framework.response import Response
|
||||
# Create your views here.
|
||||
|
||||
|
||||
class RetrieveArzeshEmtiyaz(APIView):
|
||||
def get(self, request):
|
||||
arzesh_emtiyaz = get_arzesh_emtiyaz()
|
||||
return Response({'arzesh_emtiyaz': arzesh_emtiyaz})
|
||||
|
||||
|
||||
class ListEmtiyazatApiview(ListAPIView):
|
||||
|
||||
class OuputSerializer(serializers.ModelSerializer):
|
||||
|
||||
project = inline_serializer(many=False, fields={
|
||||
'id': serializers.IntegerField(),
|
||||
'factor_price': serializers.IntegerField()
|
||||
})
|
||||
|
||||
class Meta:
|
||||
model = EmtiyazatModel
|
||||
fields = "__all__"
|
||||
|
||||
serializer_class = OuputSerializer
|
||||
pagination_class = StandardPagination
|
||||
|
||||
def get_queryset(self):
|
||||
cuser = self.request.user
|
||||
return EmtiyazatModel.objects.filter(cuser=cuser)
|
||||
Whitespace-only changes.
@@ -0,0 +1,106 @@
|
||||
from rest_framework import serializers
|
||||
from apps.cuser.models import CUser as CUserModel
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.generics import ListAPIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from utils.tools.inline_serializer import inline_serializer
|
||||
from utils.standard_pagination import StandardPagination
|
||||
from utils.order_pagination import OrderViewPagination
|
||||
from apps.order.models import Order as OrderModel
|
||||
from apps.op_panel.selector import get_orders_list, get_order
|
||||
from apps.op_panel.services import update_order
|
||||
from rest_framework import status
|
||||
|
||||
|
||||
class RetrieveOrderApiView(APIView):
|
||||
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
class OutputSerializer(serializers.Serializer):
|
||||
id = serializers.IntegerField()
|
||||
name = serializers.CharField()
|
||||
status = serializers.CharField()
|
||||
# get status choices display
|
||||
status_text = serializers.CharField(source='get_status_display')
|
||||
code = serializers.CharField()
|
||||
desc = serializers.CharField()
|
||||
cuser_mojri = inline_serializer(many=False, fields={
|
||||
'id': serializers.IntegerField(),
|
||||
'name_family': serializers.CharField(),
|
||||
'user_profile': inline_serializer(many=False, fields={
|
||||
'address': serializers.CharField()
|
||||
})
|
||||
})
|
||||
|
||||
def get(self, request, id: int):
|
||||
order = get_order(id)
|
||||
serializer = self.OutputSerializer(order)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class UpdateOrderApiView(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
class InputSerializer(serializers.Serializer):
|
||||
code = serializers.CharField()
|
||||
desc = serializers.CharField()
|
||||
|
||||
def patch(self, request, id: int):
|
||||
serializer = self.InputSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
code = serializer.validated_data['code']
|
||||
desc = serializer.validated_data['desc']
|
||||
|
||||
update_order(id, 'approve', code, desc)
|
||||
|
||||
return Response({'id': id}, status=status.HTTP_200_OK)
|
||||
|
||||
class OrderListView(ListAPIView):
|
||||
|
||||
class OutputSerializer(serializers.ModelSerializer):
|
||||
city = serializers.SerializerMethodField()
|
||||
ostan = serializers.SerializerMethodField()
|
||||
name_family = serializers.SerializerMethodField()
|
||||
mojri_id = serializers.SerializerMethodField()
|
||||
mobile = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = OrderModel
|
||||
fields = ('id', 'mojri_id', 'mobile' , 'city', 'name', 'ostan', 'name_family', 'desc', 'status')
|
||||
|
||||
def get_city(self, obj):
|
||||
if obj.cuser_mojri.user_profile.city is None:
|
||||
return ''
|
||||
return obj.cuser_mojri.user_profile.city.name
|
||||
|
||||
def get_ostan(self, obj):
|
||||
if obj.cuser_mojri.user_profile.city is None:
|
||||
return ''
|
||||
return obj.cuser_mojri.user_profile.city.ostan.name
|
||||
|
||||
def get_name_family(self, obj):
|
||||
if obj.cuser_mojri is None:
|
||||
return ''
|
||||
return obj.cuser_mojri.name_family
|
||||
|
||||
def get_mojri_id(self, obj):
|
||||
if obj.cuser_mojri is None:
|
||||
return ''
|
||||
return obj.cuser_mojri.id
|
||||
|
||||
def get_mobile(self, obj):
|
||||
if obj.cuser_mojri is None:
|
||||
return ''
|
||||
return obj.cuser_mojri.mobile
|
||||
|
||||
permission_classes = (IsAuthenticated,)
|
||||
pagination_class = OrderViewPagination
|
||||
serializer_class = OutputSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
rq_status = self.request.query_params.get('status')
|
||||
orders = get_orders_list(status=rq_status)
|
||||
return orders
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
from apps.project.models import Project as ProjectModel
|
||||
from apps.order.models import Order as OrderModel
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
|
||||
def get_order(order_id):
|
||||
try:
|
||||
order = OrderModel.objects.get(id=order_id)
|
||||
return order
|
||||
except Exception as exp:
|
||||
raise ValidationError({'error': f'error get order: {str(exp)}'})
|
||||
|
||||
|
||||
def get_orders_list(status: str = 'waiting'):
|
||||
try:
|
||||
base_filter = {}
|
||||
if status:
|
||||
base_filter['status'] = status
|
||||
|
||||
orders = OrderModel.objects.filter(**base_filter)
|
||||
return orders
|
||||
except Exception as exp:
|
||||
raise ValidationError({'error': f'error get orders: {str(exp)}'})
|
||||
|
||||
|
||||
def get_project_by_id(project_id):
|
||||
try:
|
||||
project = ProjectModel.objects.get(id=project_id)
|
||||
return project
|
||||
except Exception as exp:
|
||||
raise ValidationError({'error': f'error get project: {str(exp)}'})
|
||||
@@ -0,0 +1,33 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from apps.order.models import Order as OrderModel
|
||||
from utils.services.sms_task import task_send_sms
|
||||
CUserModel = get_user_model()
|
||||
|
||||
|
||||
def update_order(id: int, status: str, code: str, desc: str):
|
||||
try:
|
||||
OrderModel.objects.filter(id=id).update(
|
||||
code=code,
|
||||
desc=desc,
|
||||
status=status
|
||||
)
|
||||
|
||||
order = OrderModel.objects.get(id=id)
|
||||
|
||||
message = f'لوله گستر گلپایگان: مجری محترم درخواست شما برای {order.name} تایید شد '
|
||||
# build new
|
||||
|
||||
task_send_sms.delay(message=message, mobile=order.cuser_mojri.mobile)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
raise ValidationError({"error": f'error update order status ${e}'})
|
||||
|
||||
|
||||
def update_mojri_status(id: int, mojri_status: str = 'WT'):
|
||||
try:
|
||||
CUserModel.objects.filter(id=id).update(mojri_status=mojri_status)
|
||||
return True
|
||||
except Exception as e:
|
||||
raise ValidationError({"error": f'error update mojri status ${e}'})
|
||||
@@ -0,0 +1,15 @@
|
||||
from apps.op_panel.views import RetrieveProjectApiview, AddEmtiyazProjectApiview, RetrieveMojri, UpdateMojriStatusApiview
|
||||
from apps.cuser.views import ListMojrian
|
||||
from apps.op_panel.order_view import OrderListView,UpdateOrderApiView, RetrieveOrderApiView
|
||||
from django.urls import path
|
||||
|
||||
urlpatterns = [
|
||||
path('project/<int:id>/', RetrieveProjectApiview.as_view(), name='retrieve-project'),
|
||||
path('project/<int:id>/add-emtiyaz/', AddEmtiyazProjectApiview.as_view(), name='add-emtiyaz-project'),
|
||||
path('list-mojrian/', ListMojrian.as_view(), name='list-mojrian'),
|
||||
path('mojri/<int:id>/', RetrieveMojri.as_view(), name='retrieve-mojri'),
|
||||
path('mojri/<int:id>/update-status/', UpdateMojriStatusApiview.as_view(), name='update-mojri-status'),
|
||||
path('order/list/', OrderListView.as_view(), name='order-list'),
|
||||
path('order/<int:id>/update/', UpdateOrderApiView.as_view(), name='update-order'),
|
||||
path('order/<int:id>/', RetrieveOrderApiView.as_view(), name='retrieve-order'),
|
||||
]
|
||||
@@ -0,0 +1,111 @@
|
||||
from rest_framework import serializers
|
||||
from apps.project.models import Project as ProjectModel, ProjectImage as ProjectImageModel
|
||||
from apps.emtiyazat.models import Emtiyazat as EmtiyazatModel
|
||||
from apps.cuser.models import CUser as CUserModel
|
||||
from apps.op_panel.selector import get_project_by_id
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from utils.tools.inline_serializer import inline_serializer
|
||||
from apps.emtiyazat.services import add_project_emtiyaz
|
||||
from apps.op_panel.services import update_mojri_status
|
||||
from rest_framework import status
|
||||
|
||||
class UpdateMojriStatusApiview(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
class InputSerializer(serializers.Serializer):
|
||||
mojri_status = serializers.CharField()
|
||||
|
||||
def patch(self, request, id: int):
|
||||
serializer = self.InputSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
mojri_status = serializer.validated_data['mojri_status']
|
||||
|
||||
update_mojri_status(id, mojri_status)
|
||||
|
||||
return Response({'id': id}, status=status.HTTP_200_OK)
|
||||
|
||||
class RetrieveProjectApiview(APIView):
|
||||
permission_classes = (IsAuthenticated, )
|
||||
|
||||
def get(self, request, id: int):
|
||||
|
||||
class OutputSerializer(serializers.ModelSerializer):
|
||||
|
||||
cuser = inline_serializer(many=False, fields={
|
||||
'id': serializers.IntegerField(),
|
||||
'name_family': serializers.CharField(),
|
||||
'mobile': serializers.IntegerField()
|
||||
})
|
||||
|
||||
project_image = inline_serializer(many=True, fields={
|
||||
'id': serializers.IntegerField(),
|
||||
'image': serializers.ImageField(),
|
||||
})
|
||||
|
||||
class Meta:
|
||||
model = ProjectModel
|
||||
fields = '__all__'
|
||||
|
||||
project = get_project_by_id(id)
|
||||
|
||||
output = OutputSerializer(project)
|
||||
|
||||
return Response(output.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class RetrieveMojri(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
def get(self, request, id: int):
|
||||
|
||||
class OutputSerializer(serializers.ModelSerializer):
|
||||
|
||||
user_profile = inline_serializer(many=False, fields={
|
||||
'codemeli': serializers.IntegerField(),
|
||||
'city': inline_serializer(many=False, fields={
|
||||
'id': serializers.IntegerField(),
|
||||
'name': serializers.CharField(),
|
||||
'ostan': inline_serializer(many=False, fields={
|
||||
'id': serializers.IntegerField(),
|
||||
'name': serializers.CharField(),
|
||||
})
|
||||
}),
|
||||
'address': serializers.CharField(),
|
||||
'codeposti': serializers.IntegerField(),
|
||||
'ax_mojri': serializers.CharField(),
|
||||
'ax_meli': serializers.CharField(),
|
||||
'ax_fani': serializers.CharField(),
|
||||
'ax_sayer': serializers.CharField(),
|
||||
|
||||
})
|
||||
|
||||
class Meta:
|
||||
model = CUserModel
|
||||
fields = ('id', 'mojri_status', 'name_family', 'mobile', 'uuid', 'user_profile')
|
||||
|
||||
mojri = CUserModel.objects.get(id=id)
|
||||
|
||||
output = OutputSerializer(mojri)
|
||||
|
||||
return Response(output.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class AddEmtiyazProjectApiview(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
class InputSerializer(serializers.Serializer):
|
||||
credit = serializers.IntegerField(required=True)
|
||||
|
||||
def post(self, request, id: int):
|
||||
serializer = self.InputSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
op_user = request.user
|
||||
|
||||
emtiyaz = add_project_emtiyaz(**serializer.validated_data, project_id=id, op_user=op_user)
|
||||
|
||||
return Response({'success': emtiyaz.credit}, status=status.HTTP_201_CREATED)
|
||||
|
||||
Whitespace-only changes.
@@ -0,0 +1,9 @@
|
||||
from django.contrib import admin
|
||||
from apps.order.models import Order as OrderModel
|
||||
# Register your models here.
|
||||
|
||||
|
||||
@admin.register(OrderModel)
|
||||
class OrderAdmin(admin.ModelAdmin):
|
||||
list_filter = ['status']
|
||||
search_fields = ['name', 'cuser_mojri__name_family']
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class OrderConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.order'
|
||||
@@ -0,0 +1,35 @@
|
||||
# Generated by Django 4.2.1 on 2024-03-27 19:53
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('product', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Order',
|
||||
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=30)),
|
||||
('desc', models.CharField(blank=True, max_length=30, null=True)),
|
||||
('price', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('emtiyaz', models.PositiveIntegerField()),
|
||||
('cuser_mojri', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
|
||||
('product', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='product.product')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-28 07:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='order',
|
||||
name='code',
|
||||
field=models.TextField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-28 07:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0002_order_code'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='order',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('waiting', 'در انتظار برسی'), ('approve', 'تایید شد'), ('canceled', 'رد شده')], default='waiting', max_length=30),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-30 05:08
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0003_order_status'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='order',
|
||||
options={'ordering': ['-created_at']},
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,40 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db import models
|
||||
from utils.base_model import BaseModel
|
||||
from apps.product.models import Product as ProductModel
|
||||
# Create your models here.
|
||||
CUserModel = get_user_model()
|
||||
|
||||
|
||||
class Order(BaseModel):
|
||||
|
||||
STATUS_CHOICES = (
|
||||
('waiting', 'در انتظار برسی'),
|
||||
('approve', 'تایید شد'),
|
||||
('canceled', 'رد شده'),
|
||||
)
|
||||
product = models.ForeignKey(ProductModel, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
name = models.CharField(max_length=30, null=False, blank=False)
|
||||
desc = models.CharField(max_length=30, null=True, blank=True)
|
||||
code = models.TextField(null=True, blank=True)
|
||||
price = models.PositiveIntegerField(null=True, blank=True)
|
||||
emtiyaz = models.PositiveIntegerField(null=False, blank=False)
|
||||
status = models.CharField(max_length=30, choices=STATUS_CHOICES, default='waiting')
|
||||
cuser_mojri = models.ForeignKey(CUserModel, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
cuser_name = getattr(self.cuser_mojri, 'name_family', None)
|
||||
cuser_username = getattr(self.cuser_mojri, 'username', None)
|
||||
product_name = getattr(self.product, 'name', None)
|
||||
|
||||
if cuser_name and product_name:
|
||||
return f'{cuser_name} - {product_name} - {cuser_username}'
|
||||
elif cuser_name:
|
||||
return f'{ cuser_name } - {cuser_username}'
|
||||
elif product_name:
|
||||
return f'{product_name} - {cuser_username}'
|
||||
|
||||
|
||||
class Meta:
|
||||
ordering = ['-created_at']
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
from apps.order.models import Order as OrderModel
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
|
||||
def retrieve_order(order_id: int) -> OrderModel:
|
||||
try:
|
||||
order = OrderModel.objects.get(id=order_id)
|
||||
return order
|
||||
except OrderModel.DoesNotExist:
|
||||
raise ValidationError(f"Order with id {order_id} does not exist")
|
||||
except Exception as e:
|
||||
raise ValidationError(f"Error retrieving order: {e}")
|
||||
@@ -0,0 +1,46 @@
|
||||
import time
|
||||
|
||||
from apps.product.models import Product as ProductModel
|
||||
from apps.order.models import Order as OrderModel
|
||||
from apps.emtiyazat.selector import get_emtiyaz_mojri
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from apps.order.models import Order as OrderModel
|
||||
from apps.emtiyazat.services import decrease_emtiyaz
|
||||
from config.celery import app
|
||||
from celery import shared_task
|
||||
from utils.services.sms_task import task_send_sms
|
||||
#from apps.projectcode.task import generate_code
|
||||
|
||||
|
||||
def create_order(product_id: int, cuser) -> OrderModel:
|
||||
|
||||
try:
|
||||
product = ProductModel.objects.get(id=product_id)
|
||||
product_emtiyaz = product.get_emtiyaz
|
||||
emtiyaz_mojri = get_emtiyaz_mojri(cuser)
|
||||
|
||||
#generate_code.delay(count=20)
|
||||
|
||||
if emtiyaz_mojri >= product_emtiyaz:
|
||||
|
||||
decrease_emtiyaz(product_emtiyaz, desc=product.name, cuser=cuser)
|
||||
|
||||
order = OrderModel.objects.create(
|
||||
cuser_mojri=cuser,
|
||||
product=product,
|
||||
emtiyaz=product_emtiyaz,
|
||||
name=product.name,
|
||||
desc=product.desc,
|
||||
price=product.price
|
||||
)
|
||||
|
||||
message = f'لوله گستر گلپایگان: مجری محترم درخواست شما ثبت و درحال برسی است'
|
||||
task_send_sms.delay(message=message, mobile=cuser.mobile)
|
||||
|
||||
return order
|
||||
else:
|
||||
raise ValidationError({'error': 'emtiyaz mojri not enough'})
|
||||
|
||||
except Exception as exp:
|
||||
raise ValidationError({'error': f'error in create order {exp}'})
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,8 @@
|
||||
from django.urls import path
|
||||
from apps.order.views import CreateOrderApiView, RetrieveOrderApiView, ListOrderApiView
|
||||
|
||||
urlpatterns = [
|
||||
path('create/', CreateOrderApiView.as_view(), name='create_order'),
|
||||
path('list/', ListOrderApiView.as_view(), name='list_order'),
|
||||
path('<int:order_id>/', RetrieveOrderApiView.as_view(), name='retrieve_order'),
|
||||
]
|
||||
@@ -0,0 +1,88 @@
|
||||
from django.shortcuts import render
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.generics import ListAPIView
|
||||
from rest_framework import serializers
|
||||
from rest_framework import response
|
||||
from rest_framework import status
|
||||
from apps.order.models import Order as OrderModel
|
||||
from apps.order.services import create_order
|
||||
from apps.order.selector import retrieve_order
|
||||
from utils.tools.inline_serializer import inline_serializer
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from utils.standard_pagination import StandardPagination
|
||||
# Create your views here.
|
||||
|
||||
|
||||
class ListOrderApiView(ListAPIView):
|
||||
class OutputSerializer(serializers.ModelSerializer):
|
||||
|
||||
product = inline_serializer(many=False, fields={
|
||||
'id': serializers.IntegerField(),
|
||||
'desc': serializers.CharField(),
|
||||
'name': serializers.CharField(),
|
||||
'emtiyaz': serializers.IntegerField(),
|
||||
'price': serializers.IntegerField(),
|
||||
'image': serializers.ImageField(),
|
||||
})
|
||||
|
||||
status_text = serializers.CharField(source='get_status_display', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = OrderModel
|
||||
fields = '__all__'
|
||||
|
||||
permission_classes = (IsAuthenticated,)
|
||||
serializer_class = OutputSerializer
|
||||
pagination_class = StandardPagination
|
||||
|
||||
def get_queryset(self):
|
||||
user = self.request.user
|
||||
return OrderModel.objects.filter(cuser_mojri=user)
|
||||
|
||||
|
||||
class RetrieveOrderApiView(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
class OutputSerializer(serializers.ModelSerializer):
|
||||
|
||||
product = inline_serializer(many=False, fields={
|
||||
'id': serializers.IntegerField(),
|
||||
'desc': serializers.CharField(),
|
||||
'name': serializers.CharField(),
|
||||
'emtiyaz': serializers.IntegerField(),
|
||||
'price': serializers.IntegerField(),
|
||||
'image': serializers.ImageField(),
|
||||
})
|
||||
|
||||
status_text = serializers.CharField(source='get_status_display', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = OrderModel
|
||||
fields = '__all__'
|
||||
|
||||
def get(self, request, order_id):
|
||||
order = retrieve_order(order_id=order_id)
|
||||
serializer = self.OutputSerializer(order)
|
||||
return response.Response(data=serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class CreateOrderApiView(APIView):
|
||||
permission_classes = (IsAuthenticated, )
|
||||
|
||||
class InputSerializer(serializers.Serializer):
|
||||
product_id = serializers.IntegerField()
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.InputSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
user = request.user
|
||||
|
||||
order = create_order(**serializer.validated_data, cuser=user)
|
||||
|
||||
return response.Response(data={'order': order.id}, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Whitespace-only changes.
@@ -0,0 +1,14 @@
|
||||
from django.contrib import admin
|
||||
from .models import Product as ProductModel, ProductCategory as ProductCategoryModel
|
||||
# Register your models here.
|
||||
|
||||
|
||||
@admin.register(ProductCategoryModel)
|
||||
class ProductCategoryAdmin(admin.ModelAdmin):
|
||||
list_filter = ['name', 'is_enable']
|
||||
|
||||
|
||||
@admin.register(ProductModel)
|
||||
class ProductAdmin(admin.ModelAdmin):
|
||||
list_filter = ['category__name', 'is_enable']
|
||||
search_fields = ['name',]
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ProductConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.product'
|
||||
@@ -0,0 +1,38 @@
|
||||
# Generated by Django 4.2.1 on 2024-03-27 13:12
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ProductCategory',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('image', models.ImageField(blank=True, null=True, upload_to='product_category/')),
|
||||
('is_enable', models.BooleanField(default=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Product',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('price', models.PositiveIntegerField()),
|
||||
('emtiyaz', models.PositiveIntegerField()),
|
||||
('desc', models.TextField(blank=True, null=True)),
|
||||
('image', models.ImageField(blank=True, null=True, upload_to='product/')),
|
||||
('is_enable', models.BooleanField(default=True)),
|
||||
('quantity', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='product_category', to='product.productcategory')),
|
||||
],
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,32 @@
|
||||
from django.db import models
|
||||
from apps.emtiyazat.models import ArzeshEmtiyaz as ArzeshEmtiyazModel
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class ProductCategory(models.Model):
|
||||
name = models.CharField(max_length=50, null=False, blank=False)
|
||||
image = models.ImageField(upload_to='product_category/', null=True, blank=True)
|
||||
is_enable = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Product(models.Model):
|
||||
category = models.ForeignKey(ProductCategory, on_delete=models.CASCADE, related_name='product_category')
|
||||
name = models.CharField(max_length=50, null=False, blank=False)
|
||||
price = models.PositiveIntegerField(null=False, blank=False)
|
||||
emtiyaz = models.PositiveIntegerField(null=False, blank=False)
|
||||
desc = models.TextField(null=True, blank=True)
|
||||
image = models.ImageField(upload_to='product/', null=True, blank=True)
|
||||
is_enable = models.BooleanField(default=True)
|
||||
quantity = models.PositiveIntegerField(null=True, blank=True)
|
||||
|
||||
@property
|
||||
def get_emtiyaz(self):
|
||||
arzesh_obj = ArzeshEmtiyazModel.objects.filter().last()
|
||||
return self.price / arzesh_obj.price
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
from apps.product.models import Product as ProductModel
|
||||
|
||||
|
||||
def get_all_products() -> ProductModel:
|
||||
return ProductModel.objects.filter(is_enable=True, category__is_enable=True)
|
||||
Whitespace-only changes.
@@ -0,0 +1,7 @@
|
||||
from django.urls import path, include
|
||||
from apps.product.views import *
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('list/', ProductList.as_view(), name='product-list'),
|
||||
]
|
||||
@@ -0,0 +1,31 @@
|
||||
from django.shortcuts import render
|
||||
from rest_framework.views import APIView
|
||||
from apps.product.selector import get_all_products
|
||||
from rest_framework import serializers
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from utils.tools.inline_serializer import inline_serializer
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
# Create your views here.
|
||||
|
||||
|
||||
class ProductList(APIView):
|
||||
|
||||
permission_classes = (IsAuthenticated, )
|
||||
|
||||
class OutputSerializer(serializers.Serializer):
|
||||
id = serializers.IntegerField()
|
||||
category = inline_serializer(many=False, fields={
|
||||
'name': serializers.CharField(),
|
||||
})
|
||||
name = serializers.CharField()
|
||||
desc = serializers.CharField()
|
||||
emtiyaz = serializers.IntegerField()
|
||||
get_emtiyaz = serializers.IntegerField()
|
||||
image = serializers.ImageField()
|
||||
|
||||
def get(self, request):
|
||||
products = get_all_products()
|
||||
output = self.OutputSerializer(products, many=True)
|
||||
|
||||
return Response(data=output.data, status=status.HTTP_200_OK)
|
||||
Whitespace-only changes.
@@ -0,0 +1,13 @@
|
||||
from django.contrib import admin
|
||||
from apps.project.models import Project as ProjectModel, ProjectImage as ProjectImageModel
|
||||
# Register your models here.
|
||||
|
||||
|
||||
@admin.register(ProjectModel)
|
||||
class ProjectAdmin(admin.ModelAdmin):
|
||||
search_fields = ['cuser__name_family', ]
|
||||
|
||||
|
||||
@admin.register(ProjectImageModel)
|
||||
class ProjectImageAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ProjectConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.project'
|
||||
@@ -0,0 +1,50 @@
|
||||
# Generated by Django 4.2.1 on 2024-03-28 05:05
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('appsetting', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Project',
|
||||
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)),
|
||||
('address', models.CharField(max_length=200)),
|
||||
('factor_price', models.PositiveIntegerField()),
|
||||
('seller_name', models.CharField(blank=True, max_length=50, null=True)),
|
||||
('seller_mobile', models.PositiveBigIntegerField(blank=True, null=True)),
|
||||
('seller_address', models.CharField(blank=True, max_length=200, null=True)),
|
||||
('ax_factor', models.ImageField(blank=True, null=True, upload_to='project-factor/')),
|
||||
('city', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='appsetting.city')),
|
||||
('cuser', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ProjectImage',
|
||||
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)),
|
||||
('image', models.ImageField(upload_to='project/')),
|
||||
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='project.project')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-07 09:40
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('project', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='factor_price',
|
||||
field=models.PositiveBigIntegerField(),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,22 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-07 11:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('project', '0002_alter_project_factor_price'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='project',
|
||||
options={'ordering': ['-created_at']},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('waiting', 'Waiting'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='waiting', max_length=10),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-07 11:55
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('project', '0003_alter_project_options_project_status'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='op_cuser',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='projects', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-08 06:49
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('project', '0004_project_op_cuser'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('AwaitComp', 'Awaiting completion'), ('waiting', 'Waiting'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='waiting', max_length=10),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='projectimage',
|
||||
name='project',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_image', to='project.project'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-08 10:00
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('project', '0005_alter_project_status_alter_projectimage_project'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='cuser',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='mojri_projects', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-08 11:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('project', '0006_alter_project_cuser'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='tabaghat',
|
||||
field=models.PositiveIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='vahed',
|
||||
field=models.PositiveIntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='zirbana',
|
||||
field=models.PositiveIntegerField(default=0),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('AwaitComp', 'Awaiting completion'), ('waiting', 'Waiting'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='AwaitComp', max_length=10),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-09 05:07
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('project', '0007_project_tabaghat_project_vahed_project_zirbana_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='tabaghat',
|
||||
field=models.PositiveIntegerField(blank=True, default=0, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='vahed',
|
||||
field=models.PositiveIntegerField(blank=True, default=0, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='zirbana',
|
||||
field=models.PositiveIntegerField(blank=True, default=0, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-17 11:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('project', '0008_alter_project_tabaghat_alter_project_vahed_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='projectimage',
|
||||
name='image',
|
||||
field=models.ImageField(upload_to='media/project/'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-17 11:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('project', '0009_alter_projectimage_image'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='emtiyaz',
|
||||
field=models.IntegerField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
# Generated by Django 4.2.1 on 2024-05-02 06:39
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('projectcode', '0003_alter_projectcode_options_and_more'),
|
||||
('project', '0010_project_emtiyaz'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='projectcode',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='projectcode.projectcode'),
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,44 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db import models
|
||||
from utils.base_model import BaseModel
|
||||
from apps.appsetting.models import City as CityModel
|
||||
from apps.projectcode.models import ProjectCode as ProjectCodeModel
|
||||
# Create your models here.
|
||||
CUserModel = get_user_model()
|
||||
|
||||
|
||||
class Project(BaseModel):
|
||||
|
||||
status_choices = [
|
||||
('AwaitComp', 'Awaiting completion'),
|
||||
('waiting', 'Waiting'),
|
||||
('approved', 'Approved'),
|
||||
('rejected', 'Rejected'),
|
||||
]
|
||||
|
||||
cuser = models.ForeignKey(CUserModel, on_delete=models.CASCADE, null=False, blank=False, related_name='mojri_projects')
|
||||
city = models.ForeignKey(CityModel, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
address = models.CharField(max_length=200, null=False, blank=False)
|
||||
zirbana = models.PositiveIntegerField(null=True, blank=True, default=0)
|
||||
tabaghat = models.PositiveIntegerField(null=True, blank=True, default=0)
|
||||
vahed = models.PositiveIntegerField(null=True, blank=True, default=0)
|
||||
factor_price = models.PositiveBigIntegerField(null=False, blank=False)
|
||||
seller_name = models.CharField(max_length=50, null=True, blank=True)
|
||||
seller_mobile = models.PositiveBigIntegerField(null=True, blank=True)
|
||||
seller_address = models.CharField(max_length=200, null=True, blank=True)
|
||||
status = models.CharField(max_length=10, choices=status_choices, default='AwaitComp')
|
||||
op_cuser = models.ForeignKey(CUserModel, on_delete=models.SET_NULL, null=True, blank=True, related_name='projects')
|
||||
ax_factor = models.ImageField(upload_to='project-factor/', null=True, blank=True)
|
||||
emtiyaz = models.IntegerField(null=True, blank=True)
|
||||
projectcode = models.ForeignKey(ProjectCodeModel, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.cuser.name_family} - {self.city.name}'
|
||||
|
||||
class Meta:
|
||||
ordering = ['-created_at']
|
||||
|
||||
|
||||
class ProjectImage(BaseModel):
|
||||
project = models.ForeignKey(Project, models.CASCADE, null=False, blank=False, related_name='project_image')
|
||||
image = models.ImageField(upload_to='media/project/', null=False, blank=False)
|
||||
@@ -0,0 +1,20 @@
|
||||
from apps.project.models import Project as ProjectModel
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
|
||||
def op_list_project(status: str = 'waiting') -> ProjectModel:
|
||||
projects = ProjectModel.objects.filter(status=status)
|
||||
return projects
|
||||
|
||||
|
||||
def list_project(user) -> ProjectModel:
|
||||
projects = ProjectModel.objects.filter(cuser=user)
|
||||
return projects
|
||||
|
||||
|
||||
def get_project(project_id: int) -> ProjectModel:
|
||||
try:
|
||||
project = ProjectModel.objects.get(id=project_id)
|
||||
return project
|
||||
except Exception as e:
|
||||
raise ValidationError({'error': f'error on get project {str(e)}'})
|
||||
@@ -0,0 +1,52 @@
|
||||
from apps.project.models import Project as ProjectModel, ProjectImage as ProjectImageModel
|
||||
from apps.cuser.models import CUser as CUserModel
|
||||
from rest_framework.validators import ValidationError
|
||||
from utils.services.sms import DefaultSmsProvider
|
||||
from utils.services.sms_task import task_send_sms
|
||||
|
||||
def create_project(cuser: CUserModel, city: int, address: str, factor_price: int, project_images: list,
|
||||
tabaghat: int, zirbana: int, vahed:int):
|
||||
try:
|
||||
project = ProjectModel.objects.create(
|
||||
cuser=cuser,
|
||||
city_id=city,
|
||||
tabaghat=tabaghat,
|
||||
zirbana=zirbana,
|
||||
vahed=vahed,
|
||||
address=address,
|
||||
factor_price=factor_price
|
||||
)
|
||||
|
||||
for image in project_images:
|
||||
ProjectImageModel.objects.create(project=project, image=image)
|
||||
|
||||
message = f'پروژه شما با موفقیت در باشگاه مجریان لوله گستر گلپایگان ثبت شد، لطفا اطلاعات مربوط به فروشنده را تکمیل کنید.'
|
||||
task_send_sms.delay(message=message, mobile=str(cuser.mobile))
|
||||
|
||||
return project
|
||||
except Exception as e:
|
||||
raise ValidationError({'error': f'error on create project {str(e)}'})
|
||||
|
||||
|
||||
def update_seller_project(project_id: int, **kwargs):
|
||||
try:
|
||||
project = ProjectModel.objects.filter(id=project_id).update(status='waiting', **kwargs)
|
||||
project_obj = ProjectModel.objects.get(id=project_id)
|
||||
return project_obj
|
||||
except Exception as e:
|
||||
raise ValidationError({'error': f'error on update project {str(e)}'})
|
||||
|
||||
|
||||
def send_sms_to_seller(seller_mobile: int, message: str):
|
||||
sms = DefaultSmsProvider()
|
||||
sms.send_sms(str(seller_mobile), message)
|
||||
|
||||
|
||||
def update_seller_va_send_message(project_id: int, **kwargs):
|
||||
project = update_seller_project(project_id, **kwargs)
|
||||
message = f'پس از برسی و تایید پروژه توسط کارشناسان شرکت امتیاز به پروفایل شما اضافه خواهد شد'
|
||||
task_send_sms.delay(message=message, mobile=str(project.cuser.mobile))
|
||||
#send_sms_to_seller(9384999655, message)
|
||||
return project
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,12 @@
|
||||
from django.urls import path
|
||||
from apps.project.views import (CityListApiView, CreateProjectApiview, ListProjectApiview, RetrieveProjectApiview,
|
||||
UpdateSellerProjectApiview, OpListProjectApiview)
|
||||
|
||||
urlpatterns = [
|
||||
path('city-list/', CityListApiView.as_view(), name='city-list'),
|
||||
path('create/', CreateProjectApiview.as_view(), name='create-project'),
|
||||
path('list/', ListProjectApiview.as_view(), name='project-list'),
|
||||
path('op-list/', OpListProjectApiview.as_view(), name='op-project-list'),
|
||||
path('<int:project_id>/', RetrieveProjectApiview.as_view(), name='project-detail'),
|
||||
path('<int:project_id>/update-seller/', UpdateSellerProjectApiview.as_view(), name='update-seller-project'),
|
||||
]
|
||||
@@ -0,0 +1,159 @@
|
||||
from django.shortcuts import render
|
||||
from rest_framework.views import APIView
|
||||
from apps.appsetting.models import City as CityModel
|
||||
from rest_framework import serializers
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from apps.project.models import Project as ProjectModel, ProjectImage as ProjectImageModel
|
||||
from apps.appsetting.models import City as CityModel
|
||||
from apps.cuser.models import CUser as CUserModel
|
||||
from apps.project.services import create_project, update_seller_project, update_seller_va_send_message
|
||||
from apps.project.selector import list_project, get_project, op_list_project
|
||||
from apps.projectcode.selector import project_code_validation, update_project_code_used
|
||||
from apps.appsetting.selector import get_city_list
|
||||
from rest_framework import status
|
||||
# Create your views here.
|
||||
|
||||
|
||||
class CityListApiView(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
class OutputSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = CityModel
|
||||
fields = '__all__'
|
||||
|
||||
def get(self, request):
|
||||
cities = get_city_list()
|
||||
output = self.OutputSerializer(cities, many=True)
|
||||
|
||||
return Response(data=output.data)
|
||||
|
||||
|
||||
# create project with project images
|
||||
class CreateProjectApiview(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
class InputSerializer(serializers.Serializer):
|
||||
city = serializers.IntegerField(required=True)
|
||||
address = serializers.CharField(max_length=200, required=True)
|
||||
factor_price = serializers.IntegerField(required=True)
|
||||
zirbana = serializers.IntegerField(required=True)
|
||||
tabaghat = serializers.IntegerField(required=True)
|
||||
vahed = serializers.IntegerField(required=True)
|
||||
project_images = serializers.ListField(child=serializers.ImageField(), required=True)
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.InputSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
project_obj = create_project(cuser=request.user, **serializer.validated_data)
|
||||
|
||||
return Response({'project_id': f'{str(project_obj.id)}'}, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
class ListProjectApiview(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
class OutputSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = ProjectModel
|
||||
fields = '__all__'
|
||||
|
||||
def get(self, request):
|
||||
projects = list_project(user=request.user)
|
||||
output = self.OutputSerializer(projects, many=True)
|
||||
|
||||
return Response(data=output.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class RetrieveProjectApiview(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
class OutputSerializer(serializers.ModelSerializer):
|
||||
|
||||
class ProjectImageSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = ProjectImageModel
|
||||
fields = '__all__'
|
||||
|
||||
project_image = ProjectImageSerializer(many=True)
|
||||
|
||||
class Meta:
|
||||
model = ProjectModel
|
||||
fields = '__all__'
|
||||
|
||||
def get(self, request, project_id):
|
||||
project = get_project(project_id=project_id)
|
||||
output = self.OutputSerializer(project)
|
||||
|
||||
return Response(data=output.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class UpdateSellerProjectApiview(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
class InputSerializer(serializers.Serializer):
|
||||
seller_name = serializers.CharField(max_length=50, required=True)
|
||||
seller_mobile = serializers.IntegerField(required=True)
|
||||
seller_address = serializers.CharField(max_length=500, required=True)
|
||||
projectcode = serializers.CharField(max_length=20, required=True)
|
||||
|
||||
def patch(self, request, project_id):
|
||||
serializer = self.InputSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
seller_name = serializer.validated_data.get('seller_name')
|
||||
seller_mobile = serializer.validated_data.get('seller_mobile')
|
||||
seller_address = serializer.validated_data.get('seller_address')
|
||||
projectcode = serializer.validated_data.get('projectcode')
|
||||
|
||||
user = request.user
|
||||
|
||||
projectcode_obj = update_project_code_used(code=projectcode, user=user)
|
||||
|
||||
update_seller_va_send_message(
|
||||
project_id=project_id, seller_name=seller_name,
|
||||
seller_mobile=seller_mobile, seller_address=seller_address,
|
||||
projectcode=projectcode_obj
|
||||
)
|
||||
|
||||
return Response({'message': 'project updated successfully'}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class OpListProjectApiview(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
class OutputSerializer(serializers.ModelSerializer):
|
||||
|
||||
class CitySerializer(serializers.ModelSerializer):
|
||||
|
||||
class OstanSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = CityModel
|
||||
fields = '__all__'
|
||||
|
||||
ostan = OstanSerializer()
|
||||
|
||||
class Meta:
|
||||
model = CityModel
|
||||
fields = '__all__'
|
||||
|
||||
class CUserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = CUserModel
|
||||
fields = ('name_family', 'mobile',)
|
||||
|
||||
city = CitySerializer()
|
||||
cuser = CUserSerializer()
|
||||
|
||||
class Meta:
|
||||
model = ProjectModel
|
||||
fields = '__all__'
|
||||
|
||||
def get(self, request):
|
||||
project_status = request.query_params.get('status')
|
||||
projects = op_list_project(status=project_status)
|
||||
output = self.OutputSerializer(projects, many=True)
|
||||
|
||||
return Response(data=output.data, status=status.HTTP_200_OK)
|
||||
Whitespace-only changes.
@@ -0,0 +1,13 @@
|
||||
from django.contrib import admin
|
||||
from apps.projectcode.models import ProjectCode as ProjectCodeModel, ProjectCodeHead as ProjectCodeHeadModel
|
||||
|
||||
|
||||
# Register your models here.
|
||||
@admin.register(ProjectCodeHeadModel)
|
||||
class ProjectCodeHeadAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
|
||||
@admin.register(ProjectCodeModel)
|
||||
class ProjectCodeAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ProjectcodeConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.projectcode'
|
||||
@@ -0,0 +1,46 @@
|
||||
# Generated by Django 4.2.1 on 2024-04-30 05:08
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ProjectCodeHead',
|
||||
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)),
|
||||
('title', models.CharField(max_length=300)),
|
||||
('count', models.IntegerField()),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ProjectCode',
|
||||
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)),
|
||||
('code', models.CharField(max_length=20)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('is_used', models.BooleanField(default=False)),
|
||||
('mojri_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
('project_code_head', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='projectcode.projectcodehead')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
Loaded 100 of 163 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user