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 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -96,7 +99,8 @@
-
+
+
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