From f7dbd02a6c3f743c5e213f38511c4918f27aa80a Mon Sep 17 00:00:00 2001 From: javad Date: Wed, 7 Feb 2024 10:40:45 +0330 Subject: [PATCH] small changes --- .idea/workspace.xml | 18 ++-- .../0075_alter_cuserroleloginopt_uuid.py | 19 ++++ .../0076_alter_cuserroleloginopt_uuid.py | 19 ++++ .../0077_alter_cuserroleloginopt_uuid.py | 19 ++++ .../0078_alter_cuserroleloginopt_uuid.py | 19 ++++ .../0079_alter_cuserroleloginopt_uuid.py | 19 ++++ .../0080_alter_cuserroleloginopt_uuid.py | 19 ++++ .../0081_alter_cuserroleloginopt_uuid.py | 19 ++++ .../lead/migrations/0029_alter_lead_status.py | 18 ++++ .../lead/migrations/0030_alter_lead_status.py | 18 ++++ .../lead/migrations/0031_alter_lead_status.py | 18 ++++ .../lead/migrations/0032_alter_lead_status.py | 18 ++++ .../lead/migrations/0033_alter_lead_status.py | 18 ++++ .../lead/migrations/0034_alter_lead_status.py | 18 ++++ .../lead/migrations/0035_alter_lead_status.py | 18 ++++ .../migrations/0025_alter_reminder_type.py | 18 ++++ .../migrations/0026_alter_reminder_type.py | 18 ++++ .../migrations/0027_alter_reminder_type.py | 18 ++++ .../migrations/0028_alter_reminder_type.py | 18 ++++ .../migrations/0029_alter_reminder_type.py | 18 ++++ .../0014_alter_order_total_price.py | 18 ++++ apps/shop/migrations/0015_order_view_at.py | 18 ++++ .../migrations/0016_alter_orderitem_order.py | 19 ++++ ...uct_order_prd_productcategory_order_cat.py | 23 +++++ ...product_name_alter_productcategory_name.py | 23 +++++ .../migrations/0019_alter_product_price.py | 18 ++++ apps/shop/models.py | 15 ++-- apps/shop/selectors/cart.py | 2 +- apps/shop/selectors/order.py | 89 ++++++++++++++++++- apps/shop/urls.py | 6 +- apps/shop/views/__init__.py | 3 + apps/shop/views/excel_import.py | 39 ++++++++ apps/shop/views/order.py | 74 +++++++++++++++ apps/shop/views/product.py | 1 + apps/shop/views/product_category.py | 2 +- requirements/base.txt | 3 + 36 files changed, 704 insertions(+), 16 deletions(-) create mode 100644 apps/jwt_auth/migrations/0075_alter_cuserroleloginopt_uuid.py create mode 100644 apps/jwt_auth/migrations/0076_alter_cuserroleloginopt_uuid.py create mode 100644 apps/jwt_auth/migrations/0077_alter_cuserroleloginopt_uuid.py create mode 100644 apps/jwt_auth/migrations/0078_alter_cuserroleloginopt_uuid.py create mode 100644 apps/jwt_auth/migrations/0079_alter_cuserroleloginopt_uuid.py create mode 100644 apps/jwt_auth/migrations/0080_alter_cuserroleloginopt_uuid.py create mode 100644 apps/jwt_auth/migrations/0081_alter_cuserroleloginopt_uuid.py create mode 100644 apps/lead/migrations/0029_alter_lead_status.py create mode 100644 apps/lead/migrations/0030_alter_lead_status.py create mode 100644 apps/lead/migrations/0031_alter_lead_status.py create mode 100644 apps/lead/migrations/0032_alter_lead_status.py create mode 100644 apps/lead/migrations/0033_alter_lead_status.py create mode 100644 apps/lead/migrations/0034_alter_lead_status.py create mode 100644 apps/lead/migrations/0035_alter_lead_status.py create mode 100644 apps/reminder/migrations/0025_alter_reminder_type.py create mode 100644 apps/reminder/migrations/0026_alter_reminder_type.py create mode 100644 apps/reminder/migrations/0027_alter_reminder_type.py create mode 100644 apps/reminder/migrations/0028_alter_reminder_type.py create mode 100644 apps/reminder/migrations/0029_alter_reminder_type.py create mode 100644 apps/shop/migrations/0014_alter_order_total_price.py create mode 100644 apps/shop/migrations/0015_order_view_at.py create mode 100644 apps/shop/migrations/0016_alter_orderitem_order.py create mode 100644 apps/shop/migrations/0017_product_order_prd_productcategory_order_cat.py create mode 100644 apps/shop/migrations/0018_alter_product_name_alter_productcategory_name.py create mode 100644 apps/shop/migrations/0019_alter_product_price.py create mode 100644 apps/shop/views/excel_import.py diff --git a/.idea/workspace.xml b/.idea/workspace.xml index c49a91e..309a9d2 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -3,12 +3,15 @@ - - - - - - + + + + + + + + + diff --git a/apps/jwt_auth/migrations/0075_alter_cuserroleloginopt_uuid.py b/apps/jwt_auth/migrations/0075_alter_cuserroleloginopt_uuid.py new file mode 100644 index 0000000..3b1154a --- /dev/null +++ b/apps/jwt_auth/migrations/0075_alter_cuserroleloginopt_uuid.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.1 on 2024-01-27 09:24 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwt_auth', '0074_alter_cuserroleloginopt_uuid'), + ] + + operations = [ + migrations.AlterField( + model_name='cuserroleloginopt', + name='uuid', + field=models.UUIDField(default=uuid.UUID('7652353e-6437-4f8d-aa3d-b1ff9de99aac'), unique=True), + ), + ] diff --git a/apps/jwt_auth/migrations/0076_alter_cuserroleloginopt_uuid.py b/apps/jwt_auth/migrations/0076_alter_cuserroleloginopt_uuid.py new file mode 100644 index 0000000..d391e93 --- /dev/null +++ b/apps/jwt_auth/migrations/0076_alter_cuserroleloginopt_uuid.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.1 on 2024-01-27 11:50 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwt_auth', '0075_alter_cuserroleloginopt_uuid'), + ] + + operations = [ + migrations.AlterField( + model_name='cuserroleloginopt', + name='uuid', + field=models.UUIDField(default=uuid.UUID('f97fef73-113f-42f4-bd03-893cd0a6c4cd'), unique=True), + ), + ] diff --git a/apps/jwt_auth/migrations/0077_alter_cuserroleloginopt_uuid.py b/apps/jwt_auth/migrations/0077_alter_cuserroleloginopt_uuid.py new file mode 100644 index 0000000..0a852f2 --- /dev/null +++ b/apps/jwt_auth/migrations/0077_alter_cuserroleloginopt_uuid.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.1 on 2024-01-27 12:04 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwt_auth', '0076_alter_cuserroleloginopt_uuid'), + ] + + operations = [ + migrations.AlterField( + model_name='cuserroleloginopt', + name='uuid', + field=models.UUIDField(default=uuid.UUID('21a181c7-140b-4044-b43a-310712b904ba'), unique=True), + ), + ] diff --git a/apps/jwt_auth/migrations/0078_alter_cuserroleloginopt_uuid.py b/apps/jwt_auth/migrations/0078_alter_cuserroleloginopt_uuid.py new file mode 100644 index 0000000..8b830cb --- /dev/null +++ b/apps/jwt_auth/migrations/0078_alter_cuserroleloginopt_uuid.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.1 on 2024-02-06 10:23 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwt_auth', '0077_alter_cuserroleloginopt_uuid'), + ] + + operations = [ + migrations.AlterField( + model_name='cuserroleloginopt', + name='uuid', + field=models.UUIDField(default=uuid.UUID('78001c0b-3608-492f-b7c6-0a834b160c85'), unique=True), + ), + ] diff --git a/apps/jwt_auth/migrations/0079_alter_cuserroleloginopt_uuid.py b/apps/jwt_auth/migrations/0079_alter_cuserroleloginopt_uuid.py new file mode 100644 index 0000000..cd454a2 --- /dev/null +++ b/apps/jwt_auth/migrations/0079_alter_cuserroleloginopt_uuid.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.1 on 2024-02-06 10:25 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwt_auth', '0078_alter_cuserroleloginopt_uuid'), + ] + + operations = [ + migrations.AlterField( + model_name='cuserroleloginopt', + name='uuid', + field=models.UUIDField(default=uuid.UUID('66663299-ba4b-46f8-8e68-62c6be077d93'), unique=True), + ), + ] diff --git a/apps/jwt_auth/migrations/0080_alter_cuserroleloginopt_uuid.py b/apps/jwt_auth/migrations/0080_alter_cuserroleloginopt_uuid.py new file mode 100644 index 0000000..5d4ae2a --- /dev/null +++ b/apps/jwt_auth/migrations/0080_alter_cuserroleloginopt_uuid.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.1 on 2024-02-06 11:44 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwt_auth', '0079_alter_cuserroleloginopt_uuid'), + ] + + operations = [ + migrations.AlterField( + model_name='cuserroleloginopt', + name='uuid', + field=models.UUIDField(default=uuid.UUID('b639ab0a-7a39-41f2-a2cf-d65736eb71ef'), unique=True), + ), + ] diff --git a/apps/jwt_auth/migrations/0081_alter_cuserroleloginopt_uuid.py b/apps/jwt_auth/migrations/0081_alter_cuserroleloginopt_uuid.py new file mode 100644 index 0000000..fb2ce55 --- /dev/null +++ b/apps/jwt_auth/migrations/0081_alter_cuserroleloginopt_uuid.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.1 on 2024-02-06 12:30 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('jwt_auth', '0080_alter_cuserroleloginopt_uuid'), + ] + + operations = [ + migrations.AlterField( + model_name='cuserroleloginopt', + name='uuid', + field=models.UUIDField(default=uuid.UUID('8f0b7e63-3d78-4de2-9e59-931a8734fc02'), unique=True), + ), + ] diff --git a/apps/lead/migrations/0029_alter_lead_status.py b/apps/lead/migrations/0029_alter_lead_status.py new file mode 100644 index 0000000..c351428 --- /dev/null +++ b/apps/lead/migrations/0029_alter_lead_status.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-01-27 09:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lead', '0028_alter_lead_status'), + ] + + operations = [ + migrations.AlterField( + model_name='lead', + name='status', + field=models.CharField(blank=True, choices=[('UN', 'unknown'), ('FA', 'FAIL'), ('SU', 'OK')], default='UN', max_length=2, null=True), + ), + ] diff --git a/apps/lead/migrations/0030_alter_lead_status.py b/apps/lead/migrations/0030_alter_lead_status.py new file mode 100644 index 0000000..6db67c2 --- /dev/null +++ b/apps/lead/migrations/0030_alter_lead_status.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-01-27 11:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lead', '0029_alter_lead_status'), + ] + + operations = [ + migrations.AlterField( + model_name='lead', + name='status', + field=models.CharField(blank=True, choices=[('SU', 'OK'), ('FA', 'FAIL'), ('UN', 'unknown')], default='UN', max_length=2, null=True), + ), + ] diff --git a/apps/lead/migrations/0031_alter_lead_status.py b/apps/lead/migrations/0031_alter_lead_status.py new file mode 100644 index 0000000..21f0553 --- /dev/null +++ b/apps/lead/migrations/0031_alter_lead_status.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-01-27 12:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lead', '0030_alter_lead_status'), + ] + + operations = [ + migrations.AlterField( + model_name='lead', + name='status', + field=models.CharField(blank=True, choices=[('UN', 'unknown'), ('SU', 'OK'), ('FA', 'FAIL')], default='UN', max_length=2, null=True), + ), + ] diff --git a/apps/lead/migrations/0032_alter_lead_status.py b/apps/lead/migrations/0032_alter_lead_status.py new file mode 100644 index 0000000..02062fb --- /dev/null +++ b/apps/lead/migrations/0032_alter_lead_status.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-02-06 10:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lead', '0031_alter_lead_status'), + ] + + operations = [ + migrations.AlterField( + model_name='lead', + name='status', + field=models.CharField(blank=True, choices=[('UN', 'unknown'), ('FA', 'FAIL'), ('SU', 'OK')], default='UN', max_length=2, null=True), + ), + ] diff --git a/apps/lead/migrations/0033_alter_lead_status.py b/apps/lead/migrations/0033_alter_lead_status.py new file mode 100644 index 0000000..9f7ee0e --- /dev/null +++ b/apps/lead/migrations/0033_alter_lead_status.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-02-06 10:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lead', '0032_alter_lead_status'), + ] + + operations = [ + migrations.AlterField( + model_name='lead', + name='status', + field=models.CharField(blank=True, choices=[('SU', 'OK'), ('FA', 'FAIL'), ('UN', 'unknown')], default='UN', max_length=2, null=True), + ), + ] diff --git a/apps/lead/migrations/0034_alter_lead_status.py b/apps/lead/migrations/0034_alter_lead_status.py new file mode 100644 index 0000000..8b35015 --- /dev/null +++ b/apps/lead/migrations/0034_alter_lead_status.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-02-06 11:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lead', '0033_alter_lead_status'), + ] + + operations = [ + migrations.AlterField( + model_name='lead', + name='status', + field=models.CharField(blank=True, choices=[('FA', 'FAIL'), ('SU', 'OK'), ('UN', 'unknown')], default='UN', max_length=2, null=True), + ), + ] diff --git a/apps/lead/migrations/0035_alter_lead_status.py b/apps/lead/migrations/0035_alter_lead_status.py new file mode 100644 index 0000000..f17eabe --- /dev/null +++ b/apps/lead/migrations/0035_alter_lead_status.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-02-06 12:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lead', '0034_alter_lead_status'), + ] + + operations = [ + migrations.AlterField( + model_name='lead', + name='status', + field=models.CharField(blank=True, choices=[('SU', 'OK'), ('FA', 'FAIL'), ('UN', 'unknown')], default='UN', max_length=2, null=True), + ), + ] diff --git a/apps/reminder/migrations/0025_alter_reminder_type.py b/apps/reminder/migrations/0025_alter_reminder_type.py new file mode 100644 index 0000000..ddf3390 --- /dev/null +++ b/apps/reminder/migrations/0025_alter_reminder_type.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-01-27 09:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reminder', '0024_alter_reminder_type'), + ] + + operations = [ + migrations.AlterField( + model_name='reminder', + name='type', + field=models.CharField(choices=[('LE', 'LEAD'), ('CU', 'CUSTOMER'), ('UN', 'UNKNOWN'), ('NO', 'NOTE')], default='UN', max_length=2), + ), + ] diff --git a/apps/reminder/migrations/0026_alter_reminder_type.py b/apps/reminder/migrations/0026_alter_reminder_type.py new file mode 100644 index 0000000..b7103a0 --- /dev/null +++ b/apps/reminder/migrations/0026_alter_reminder_type.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-01-27 12:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reminder', '0025_alter_reminder_type'), + ] + + operations = [ + migrations.AlterField( + model_name='reminder', + name='type', + field=models.CharField(choices=[('UN', 'UNKNOWN'), ('LE', 'LEAD'), ('CU', 'CUSTOMER'), ('NO', 'NOTE')], default='UN', max_length=2), + ), + ] diff --git a/apps/reminder/migrations/0027_alter_reminder_type.py b/apps/reminder/migrations/0027_alter_reminder_type.py new file mode 100644 index 0000000..86d8101 --- /dev/null +++ b/apps/reminder/migrations/0027_alter_reminder_type.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-02-06 10:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reminder', '0026_alter_reminder_type'), + ] + + operations = [ + migrations.AlterField( + model_name='reminder', + name='type', + field=models.CharField(choices=[('LE', 'LEAD'), ('NO', 'NOTE'), ('UN', 'UNKNOWN'), ('CU', 'CUSTOMER')], default='UN', max_length=2), + ), + ] diff --git a/apps/reminder/migrations/0028_alter_reminder_type.py b/apps/reminder/migrations/0028_alter_reminder_type.py new file mode 100644 index 0000000..a50a1b8 --- /dev/null +++ b/apps/reminder/migrations/0028_alter_reminder_type.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-02-06 10:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reminder', '0027_alter_reminder_type'), + ] + + operations = [ + migrations.AlterField( + model_name='reminder', + name='type', + field=models.CharField(choices=[('LE', 'LEAD'), ('UN', 'UNKNOWN'), ('NO', 'NOTE'), ('CU', 'CUSTOMER')], default='UN', max_length=2), + ), + ] diff --git a/apps/reminder/migrations/0029_alter_reminder_type.py b/apps/reminder/migrations/0029_alter_reminder_type.py new file mode 100644 index 0000000..7969a4a --- /dev/null +++ b/apps/reminder/migrations/0029_alter_reminder_type.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-02-06 12:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reminder', '0028_alter_reminder_type'), + ] + + operations = [ + migrations.AlterField( + model_name='reminder', + name='type', + field=models.CharField(choices=[('NO', 'NOTE'), ('UN', 'UNKNOWN'), ('CU', 'CUSTOMER'), ('LE', 'LEAD')], default='UN', max_length=2), + ), + ] diff --git a/apps/shop/migrations/0014_alter_order_total_price.py b/apps/shop/migrations/0014_alter_order_total_price.py new file mode 100644 index 0000000..22904fa --- /dev/null +++ b/apps/shop/migrations/0014_alter_order_total_price.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-01-27 09:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('shop', '0013_alter_productcategory_image'), + ] + + operations = [ + migrations.AlterField( + model_name='order', + name='total_price', + field=models.PositiveIntegerField(), + ), + ] diff --git a/apps/shop/migrations/0015_order_view_at.py b/apps/shop/migrations/0015_order_view_at.py new file mode 100644 index 0000000..edc7da8 --- /dev/null +++ b/apps/shop/migrations/0015_order_view_at.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-01-27 11:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('shop', '0014_alter_order_total_price'), + ] + + operations = [ + migrations.AddField( + model_name='order', + name='view_at', + field=models.DateTimeField(blank=True, default=None, null=True), + ), + ] diff --git a/apps/shop/migrations/0016_alter_orderitem_order.py b/apps/shop/migrations/0016_alter_orderitem_order.py new file mode 100644 index 0000000..78a1059 --- /dev/null +++ b/apps/shop/migrations/0016_alter_orderitem_order.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.1 on 2024-01-27 12:04 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('shop', '0015_order_view_at'), + ] + + operations = [ + migrations.AlterField( + model_name='orderitem', + name='order', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='order_item', to='shop.order'), + ), + ] diff --git a/apps/shop/migrations/0017_product_order_prd_productcategory_order_cat.py b/apps/shop/migrations/0017_product_order_prd_productcategory_order_cat.py new file mode 100644 index 0000000..e0a1d63 --- /dev/null +++ b/apps/shop/migrations/0017_product_order_prd_productcategory_order_cat.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.1 on 2024-02-06 10:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('shop', '0016_alter_orderitem_order'), + ] + + operations = [ + migrations.AddField( + model_name='product', + name='order_prd', + field=models.PositiveIntegerField(blank=True, default=None, null=True), + ), + migrations.AddField( + model_name='productcategory', + name='order_cat', + field=models.PositiveIntegerField(blank=True, default=None, null=True), + ), + ] diff --git a/apps/shop/migrations/0018_alter_product_name_alter_productcategory_name.py b/apps/shop/migrations/0018_alter_product_name_alter_productcategory_name.py new file mode 100644 index 0000000..a4e499b --- /dev/null +++ b/apps/shop/migrations/0018_alter_product_name_alter_productcategory_name.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.1 on 2024-02-06 11:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('shop', '0017_product_order_prd_productcategory_order_cat'), + ] + + operations = [ + migrations.AlterField( + model_name='product', + name='name', + field=models.CharField(max_length=200), + ), + migrations.AlterField( + model_name='productcategory', + name='name', + field=models.CharField(max_length=60), + ), + ] diff --git a/apps/shop/migrations/0019_alter_product_price.py b/apps/shop/migrations/0019_alter_product_price.py new file mode 100644 index 0000000..a87440d --- /dev/null +++ b/apps/shop/migrations/0019_alter_product_price.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.1 on 2024-02-06 12:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('shop', '0018_alter_product_name_alter_productcategory_name'), + ] + + operations = [ + migrations.AlterField( + model_name='product', + name='price', + field=models.PositiveBigIntegerField(), + ), + ] diff --git a/apps/shop/models.py b/apps/shop/models.py index cf90ff7..5dfef47 100644 --- a/apps/shop/models.py +++ b/apps/shop/models.py @@ -1,3 +1,5 @@ +from turtle import mode + from django.db import models from utils.base_model import BaseModel from apps.workspace.models import Workspace as WorkspaceModel @@ -15,9 +17,10 @@ class ProductType(BaseModel): class ProductCategory(BaseModel): - name = models.CharField(max_length=30, null=False, blank=False) + name = models.CharField(max_length=60, null=False, blank=False) parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True) image = models.ImageField(null=True, blank=True, default=None, upload_to='product-cat/') + order_cat = models.PositiveIntegerField(null=True, blank=True, default=None) sys_ws = models.ForeignKey(WorkspaceModel, on_delete=models.CASCADE, null=False, blank=False) def __str__(self): @@ -25,10 +28,11 @@ class ProductCategory(BaseModel): class Product(BaseModel): - name = models.CharField(max_length=150, null=False, blank=False) - price = models.DecimalField(max_digits=12, decimal_places=2, null=False, blank=False) + name = models.CharField(max_length=200, null=False, blank=False) + price = models.PositiveBigIntegerField(null=False, blank=False) category = models.ForeignKey(ProductCategory, on_delete=models.CASCADE, null=False, blank=False) acc_code = models.CharField(null=True, blank=True) + order_prd = models.PositiveIntegerField(null=True, blank=True, default=None) attr = models.JSONField(null=True, blank=True) sys_ws = models.ForeignKey(WorkspaceModel, on_delete=models.CASCADE, null=False, blank=False) @@ -63,17 +67,18 @@ class Order(BaseModel): responsible_group = models.ForeignKey(ResponsibleGroupModel, on_delete=models.SET_NULL, null=True, blank=True) customer = models.ForeignKey(CustomerModel, on_delete=models.CASCADE, null=False, blank=False) - total_price = models.DecimalField(max_digits=12, decimal_places=2, null=False, blank=False) + total_price = models.PositiveIntegerField(null=False, blank=False) factor_type = models.PositiveSmallIntegerField(choices=FACTOR_TYPE_CHOICE, null=False, blank=False) factor_status = models.PositiveSmallIntegerField(choices=FACTOR_STATUS_CHOICE, null=True, blank=True) sys_ws = models.ForeignKey(WorkspaceModel, on_delete=models.CASCADE, null=False, blank=False) + view_at = models.DateTimeField(null=True, blank=True, default=None) def __str__(self): return f'{self.customer}' class OrderItem(BaseModel): - order = models.ForeignKey(Order, on_delete=models.CASCADE, null=False, blank=False) + order = models.ForeignKey(Order, on_delete=models.CASCADE, null=False, blank=False, related_name='order_item') product = models.ForeignKey(Product, on_delete=models.CASCADE, null=False, blank=False) product_name = models.CharField(max_length=150, null=False, blank=False) price = models.DecimalField(max_digits=12, decimal_places=2, null=False, blank=False) diff --git a/apps/shop/selectors/cart.py b/apps/shop/selectors/cart.py index 8fa69f8..32af522 100644 --- a/apps/shop/selectors/cart.py +++ b/apps/shop/selectors/cart.py @@ -2,7 +2,7 @@ from apps.shop.models import Cart as CartModel def list_cart(cuser_role_uuid: str, workspace_uuid: str) -> CartModel: - return CartModel.objects.filter(sys_ws__uuid=workspace_uuid, cuser_role__uuid=cuser_role_uuid) + return CartModel.objects.filter(sys_ws__uuid=workspace_uuid, cuser_role__uuid=cuser_role_uuid).order_by('-created_at') def clean_cart(cuser_role_uuid: str, workspace_uuid: str) -> CartModel: diff --git a/apps/shop/selectors/order.py b/apps/shop/selectors/order.py index 26d5108..ca2c2ed 100644 --- a/apps/shop/selectors/order.py +++ b/apps/shop/selectors/order.py @@ -1,9 +1,14 @@ -from apps.shop.models import Order as OrderModel +from apps.shop.models import Order as OrderModel, OrderItem as OrderItemModel from apps.customer.models import CustomerResponsible as CustomerResponsibleModel from apps.cuser.models import CuserRole as CuserRoleModel from rest_framework import exceptions from utils.custom_permissions import workspace_admin_up +from utils.get_user_workspace import get_user_workspace_uuid, get_user_workspace +from utils.get_cuser_role import get_cuser_role, get_cuser_role_uuid from apps.customer.models import Customer as CustomerModel +from django.http import HttpResponse +import pandas as pd +from django.utils import timezone def retrieve_order(cuser_role_uuid: str, order_id: int, workspace_uuid: str) -> OrderModel: @@ -44,3 +49,85 @@ def list_order(cuser_role_uuid: str, workspace_uuid: str) -> OrderModel: except Exception as exp: message = f'Error Fetching List Order: {exp}' raise exceptions.ValidationError({'error': message}) + + +def list_order_operators(request) -> OrderModel: + try: + workspace_uuid = get_user_workspace_uuid(request) + cuser_role_uuid = get_cuser_role_uuid(request) + customer_responsibles = CustomerResponsibleModel.objects.filter(cuser_role__uuid=cuser_role_uuid, sys_ws__uuid=workspace_uuid) + responsible_group_ids = customer_responsibles.values_list('responsible_group__id', flat=True) + + orders = OrderModel.objects.filter(sys_ws__uuid=workspace_uuid, + responsible_group_id__in=responsible_group_ids).order_by('-created_at')[:10] + return orders + except Exception as exp: + message = f'Error Fetching List Order: {exp}' + raise exceptions.ValidationError({'error': message}) + + +def retrieve_order_operators(request, order_id) -> OrderModel: + try: + workspace_uuid = get_user_workspace_uuid(request) + cuser_role_uuid = get_cuser_role_uuid(request) + customer_responsibles = CustomerResponsibleModel.objects.filter(cuser_role__uuid=cuser_role_uuid, sys_ws__uuid=workspace_uuid) + responsible_group_ids = customer_responsibles.values_list('responsible_group__id', flat=True) + + order = OrderModel.objects.get(id=order_id, sys_ws__uuid=workspace_uuid, + responsible_group_id__in=responsible_group_ids) + order.view_at = timezone.now() + order.save() + + return order + except Exception as exp: + message = f'Error Retrive Order: {exp}' + raise exceptions.ValidationError({'error': message}) + + +def retrieve_order_item_excel(request, order_id): + try: + workspace_uuid = get_user_workspace_uuid(request) + cuser_role_uuid = get_cuser_role_uuid(request) + customer_responsibles = CustomerResponsibleModel.objects.filter(cuser_role__uuid=cuser_role_uuid, + sys_ws__uuid=workspace_uuid) + + responsible_group_ids = customer_responsibles.values_list('responsible_group__id', flat=True) + + order_items = OrderItemModel.objects.filter(order_id=order_id, + order__responsible_group_id__in=responsible_group_ids) + + df = pd.DataFrame(list(order_items.values('product__acc_code', 'product__category__name', 'product_name', 'amount', 'product__attr__acc_vahed'))) + + #df['واحد سنجش'] = '' + df['عامل کنترل موجودی اول'] = '' + df['عامل کنترل موجودی دوم'] = '' + df['عامل کنترل موجودی سوم'] = '' + df['عامل کنترل موجودی سوم'] = '' + df['عامل کنترل موجودی چهارم'] = '' + df['عامل کنترل موجودی پنجم'] = '' + + df['محصول'] = df['product__category__name'] + df['product_name'] + df = df.drop(columns=['product__category__name', 'product_name']) + + df.rename(columns={ + 'product__acc_code': ' کد محصول', + 'amount': 'مقدار', + 'product__attr__acc_vahed': 'واحد سنجش' + + }, inplace=True) + + df = df[['محصول', + ' کد محصول', + 'واحد سنجش', + 'عامل کنترل موجودی اول', + 'عامل کنترل موجودی دوم', + 'عامل کنترل موجودی سوم', + 'عامل کنترل موجودی چهارم', + 'عامل کنترل موجودی پنجم', + 'مقدار', + ]] + + return df + except Exception as exp: + message = f'Error Retrive Order Items for excel: {exp}' + raise exceptions.ValidationError({'error': message}) diff --git a/apps/shop/urls.py b/apps/shop/urls.py index 8e18d1b..f30f27f 100644 --- a/apps/shop/urls.py +++ b/apps/shop/urls.py @@ -23,7 +23,9 @@ urlpatterns = [ path('order/update//', OrderUpdateApi.as_view(), name='update_order'), path('order/delete//', OrderDeleteApi.as_view(), name='delete_order'), path('order/list/', OrderListApi.as_view(), name='list_order'), - + path('order/list-operator/', OrderListOperatorApi.as_view(), name='list_order_operator'), + path('order//operator/', OrderRetrieveOperatorApi.as_view(), name='order_retrieve_operator'), + path('order//operator/excel/', OrderRetrieveOperatorExcelApi.as_view(), name='order_retrieve_operator_excel'), path('order/iteams/list//', OrderItemsListApi.as_view(), name='list_order_items'), @@ -31,4 +33,6 @@ urlpatterns = [ path('cart/', CartListApi.as_view(), name='list_cart'), path('cart/add/', CartCreateApi.as_view(), name='add_cart'), path('cart/delete//', CartDeleteApi.as_view(), name='delete_cart'), + + #path('import/', ImportExcelView.as_view(), name='import_excel'), ] diff --git a/apps/shop/views/__init__.py b/apps/shop/views/__init__.py index 6662d7d..6d4909b 100644 --- a/apps/shop/views/__init__.py +++ b/apps/shop/views/__init__.py @@ -8,9 +8,12 @@ from .product import ( ) from .order import ( + OrderListOperatorApi, OrderRetrieveOperatorApi, OrderRetrieveOperatorExcelApi, OrderCreateApi, OrderUpdateApi, OrderDeleteApi, OrderRetrieveApi, OrderListApi, OrderAndItemCreateApi ) from .cart import (CartListApi, CartCreateApi, CartDeleteApi) from .order_item import (OrderItemsListApi, ) + +from .excel_import import ImportExcelView diff --git a/apps/shop/views/excel_import.py b/apps/shop/views/excel_import.py new file mode 100644 index 0000000..7511237 --- /dev/null +++ b/apps/shop/views/excel_import.py @@ -0,0 +1,39 @@ +from rest_framework.views import APIView +from rest_framework.response import Response +import pandas as pd +from apps.shop.models import Product as ProductModel, ProductCategory as ProductCategoryModel +from apps.workspace.models import Workspace as WorkspaceModel +import os + + +class ImportExcelView(APIView): + + def get(self, request): + + df = pd.read_excel('pe.xlsx') + for index, row in df.iterrows(): + cate_name = row['cate_name'] + order_cat = row['order_cat'] + acc_code = row['acc_code'] + prd_name = row['prd_name'] + order_prd = row['order_prd'] + vahed = row['vahed'] + + workspace = WorkspaceModel.objects.get(id=2) + try: + prd_ct = ProductCategoryModel.objects.get(name=cate_name, sys_ws=workspace, order_cat=order_cat) + except ProductCategoryModel.DoesNotExist as exp: + prd_ct = ProductCategoryModel.objects.create(name=cate_name, sys_ws=workspace, order_cat=order_cat) + + new_product = ProductModel() + new_product.name = prd_name + new_product.price = 0 + new_product.category = ProductCategoryModel.objects.get(id=prd_ct.id) + new_product.acc_code = acc_code + new_product.order_prd = order_prd + new_product.attr = {"acc_vahed": vahed} + new_product.sys_ws = workspace + new_product.save() + + return Response(data={"result": 'ok'}) + diff --git a/apps/shop/views/order.py b/apps/shop/views/order.py index 25a55cd..ba925d7 100644 --- a/apps/shop/views/order.py +++ b/apps/shop/views/order.py @@ -11,6 +11,9 @@ from rest_framework import generics from apps.customer.models import Customer as CustomerModel from rest_framework.permissions import IsAuthenticated from utils import custom_permissions +from utils.tools import inline_serializer +from io import BytesIO + class OrderCreateApi(APIView): @@ -150,3 +153,74 @@ class OrderListApi(generics.ListAPIView): return list_order(cuser_role_uuid=cuser_role_uuid, workspace_uuid=user_workspace_uuid) + +class OrderListOperatorApi(generics.ListAPIView): + class OutputSerializer(serializers.ModelSerializer): + customer = inline_serializer(fields={ + 'id': serializers.IntegerField(), + 'name_family': serializers.CharField(), + }) + class Meta: + model = OrderModel + exclude = ('sys_ws', ) + + serializer_class = OutputSerializer + + def get_queryset(self): + + return list_order_operators(self.request) + + +class OrderRetrieveOperatorApi(APIView): + class OutputSerializer(serializers.ModelSerializer): + + customer = inline_serializer(fields={ + 'id': serializers.IntegerField(), + 'name_family': serializers.CharField(), + }) + + order_item = inline_serializer(many=True, fields={ + 'id': serializers.IntegerField(), + 'product': inline_serializer(fields={ + 'id': serializers.IntegerField(), + 'name': serializers.CharField(), + 'category': inline_serializer(fields={ + 'id': serializers.IntegerField(), + 'name': serializers.CharField(), + }) + }), + 'product_name': serializers.CharField(), + 'price': serializers.IntegerField(), + 'amount': serializers.IntegerField(), + }) + + class Meta: + model = OrderModel + exclude = ('sys_ws', ) + + serializer_class = OutputSerializer + + def get(self, request, order_id): + + order = retrieve_order_operators(request, order_id=order_id) + + output = self.OutputSerializer(order) + + return Response(data=output.data, status=status.HTTP_200_OK) + + +class OrderRetrieveOperatorExcelApi(APIView): + def get(self, request, order_id): + + order_df = retrieve_order_item_excel(request=request, order_id=order_id) + + excel_file = BytesIO() + order_df.to_excel(excel_file, engine='xlsxwriter', index=False) + excel_file.seek(0) + + response = HttpResponse(excel_file.read(), content_type='application/ms-excel') + response['Content-Disposition'] = 'attachment; filename="output.xlsx"' + + return response + + diff --git a/apps/shop/views/product.py b/apps/shop/views/product.py index 0366e1f..12e03ea 100644 --- a/apps/shop/views/product.py +++ b/apps/shop/views/product.py @@ -151,6 +151,7 @@ class ProductListCategoryApi(generics.ListAPIView): ) data = { "category_name": category.name, + "category_img": category.image.url, "products": serializer.data } diff --git a/apps/shop/views/product_category.py b/apps/shop/views/product_category.py index 9812f46..0d4843b 100644 --- a/apps/shop/views/product_category.py +++ b/apps/shop/views/product_category.py @@ -156,7 +156,7 @@ class ProductsCategoryApi(APIView): def get(self, request): - p_cate = ProductCategoryModel.objects.annotate(product_count=Count('product')).filter(product_count__gte=1) + p_cate = ProductCategoryModel.objects.annotate(product_count=Count('product')).filter(product_count__gte=1).order_by('order_cat') output = self.OutputSerializer(p_cate, many=True) return Response(data=output.data, status=status.HTTP_200_OK) diff --git a/requirements/base.txt b/requirements/base.txt index 45a7976..46927b3 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -6,4 +6,7 @@ drf-spectacular==0.26.2 psycopg==3.1.9 djangorestframework-simplejwt==5.2.2 django-cors-headers==4.3.1 +openpyxl==3.1.2 +XlsxWriter==3.1.9 +pandas==2.2.0 pillow==10.2.0 \ No newline at end of file