diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml
index f546d57..f56d882 100644
--- a/.github/workflows/deploy.yaml
+++ b/.github/workflows/deploy.yaml
@@ -34,6 +34,10 @@ jobs:
mkdir -p /root/hshop/backend/
printf "%s" "${{ secrets.ENV_FILE_CONTENT }}" > /root/hshop/backend/.env.local
+ mkdir -p /root/hshop/frontend/
+ printf "%s" "${{ secrets.FRONTEND_ENV }}" > /root/hshop/frontend/.env
+
+
- name: Build and start Docker containers
uses: appleboy/ssh-action@v0.1.6
with:
diff --git a/backend/account/migrations/0025_alter_pushsubscription_options_and_more.py b/backend/account/migrations/0025_alter_pushsubscription_options_and_more.py
new file mode 100644
index 0000000..fbf9933
--- /dev/null
+++ b/backend/account/migrations/0025_alter_pushsubscription_options_and_more.py
@@ -0,0 +1,22 @@
+# Generated by Django 5.1.2 on 2025-03-28 15:39
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('account', '0024_alter_user_birth_date'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='pushsubscription',
+ options={'verbose_name': 'اشتراک نوتیفیکیشن', 'verbose_name_plural': 'اشتراک های نوتیفیکیشن'},
+ ),
+ migrations.AlterField(
+ model_name='useraddressmodel',
+ name='is_main',
+ field=models.BooleanField(default=False, verbose_name='ادرس اصلی کاربر'),
+ ),
+ ]
diff --git a/backend/azbankgateways/migrations/0008_alter_bank_order.py b/backend/azbankgateways/migrations/0008_alter_bank_order.py
new file mode 100644
index 0000000..72bd58e
--- /dev/null
+++ b/backend/azbankgateways/migrations/0008_alter_bank_order.py
@@ -0,0 +1,20 @@
+# Generated by Django 5.1.2 on 2025-03-28 15:39
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('azbankgateways', '0007_alter_bank_order'),
+ ('order', '0025_alter_ordermodel_order_id'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='bank',
+ name='order',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bank_records', to='order.ordermodel', verbose_name='سفارش'),
+ ),
+ ]
diff --git a/backend/core/settings/base.py b/backend/core/settings/base.py
index 4710cfd..14c58ba 100644
--- a/backend/core/settings/base.py
+++ b/backend/core/settings/base.py
@@ -244,7 +244,7 @@ AZ_IRANIAN_BANK_GATEWAYS = {
"ZIBAL": {
"MERCHANT_CODE": "zibal",
"SANDBOX": True
- },
+ }
},
"IS_SAMPLE_FORM_ENABLE": True,
"DEFAULT": "ZIBAL",
@@ -255,5 +255,6 @@ AZ_IRANIAN_BANK_GATEWAYS = {
"BANK_PRIORITIES": [
"ZIBAL",
],
- "IS_SAFE_GET_GATEWAY_PAYMENT": False # better to be True
-}
\ No newline at end of file
+ "IS_SAFE_GET_GATEWAY_PAYMENT": True # better to be True
+}
+DEFAULT_TAX_RATE = 20
\ No newline at end of file
diff --git a/backend/core/settings/production.py b/backend/core/settings/production.py
index a641284..b6d1107 100644
--- a/backend/core/settings/production.py
+++ b/backend/core/settings/production.py
@@ -2,7 +2,7 @@ from .base import *
from .unfold_conf import *
-ALLOWED_HOSTS = ['127.0.0.1', 'localhost', DOMAIN, API_DOMAIN]
+ALLOWED_HOSTS = ['127.0.0.1', 'localhost', DOMAIN, API_DOMAIN, '0.0.0.0',]
CSRF_TRUSTED_ORIGINS = [
f"https://{DOMAIN}",
f"http://{DOMAIN}",
diff --git a/backend/core/views.py b/backend/core/views.py
index d57f36a..be623df 100644
--- a/backend/core/views.py
+++ b/backend/core/views.py
@@ -52,7 +52,7 @@ def random_data():
"kpi": [
{
"title": "گوشی Iphone 16 pro",
- "metric": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}",
+ "metric": f"${intcomma(f'{random.uniform(1000, 9999):.02f}')}",
"footer": mark_safe(
f'+{intcomma(f"{random.uniform(1, 9):.02f}")}% درصد فروش کل'
),
@@ -65,14 +65,14 @@ def random_data():
},
{
"title": "لپ تاپ Macbook Pro M3",
- "metric": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}",
+ "metric": f"${intcomma(f'{random.uniform(1000, 9999):.02f}')}",
"footer": mark_safe(
f'+{intcomma(f"{random.uniform(1, 9):.02f}")}% درصد فروش کل'
),
},
{
"title": "ساعت هوشمند Apple Watch 8",
- "metric": f"${intcomma(f"{random.uniform(1000, 9999):.02f}")}",
+ "metric": f"${intcomma(f'{random.uniform(1000, 9999):.02f}')}",
"footer": mark_safe(
f'+{intcomma(f"{random.uniform(1, 9):.02f}")}% درصد فروش کل'
),
diff --git a/backend/order/migrations/0025_alter_ordermodel_order_id.py b/backend/order/migrations/0025_alter_ordermodel_order_id.py
new file mode 100644
index 0000000..5c1df71
--- /dev/null
+++ b/backend/order/migrations/0025_alter_ordermodel_order_id.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.1.2 on 2025-03-28 15:39
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('order', '0024_orderitemmodel_discount_ordermodel_order_id'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='ordermodel',
+ name='order_id',
+ field=models.PositiveIntegerField(blank=True, null=True, unique=True, verbose_name='شماره سفارش'),
+ ),
+ ]
diff --git a/backend/order/models.py b/backend/order/models.py
index 8d7ba6a..675bd07 100644
--- a/backend/order/models.py
+++ b/backend/order/models.py
@@ -66,9 +66,11 @@ class OrderModel(models.Model):
def save(self, *args, **kwargs):
+ # genrate order id
if not self.pk:
last_instance = self.__class__.objects.order_by("pk").last()
self.order_id = (last_instance.pk + 1001) if last_instance else 1001
+
super().save(*args, **kwargs)
diff --git a/backend/order/signals.py b/backend/order/signals.py
index 63cacc1..793f46e 100644
--- a/backend/order/signals.py
+++ b/backend/order/signals.py
@@ -3,6 +3,8 @@ from django.dispatch import receiver
from .models import OrderModel
from account.models import PushSubscription
import ghasedak_sms
+from .tasks import send_change_status_notif, send_change_status_sms
+
@receiver(pre_save, sender=OrderModel)
def order_status_changed(sender, instance, **kwargs):
@@ -10,36 +12,18 @@ def order_status_changed(sender, instance, **kwargs):
previous = OrderModel.objects.get(pk=instance.pk)
if previous.status != instance.status:
- send_change_status_notif(instance)
- send_change_status_sms(instance)
+ new_status = instance.get_status_display()
+ send_change_status_notif.delay(instance.pk, new_status)
+ send_change_status_sms.delay(instance.pk, new_status)
+
+ if previous.status == 'CART' and instance.status == 'ADMIN_PENDING':
+ # update_cart_price_fields()
+ # update_sell_data()
+ # update_quantity()
+ pass
-def send_change_status_notif(instance):
- user_subs = PushSubscription.objects.filter(user=instance.user)
- for user_sub in user_subs:
- try:
- user_sub.send_notif(f'سفارش شما به {instance.get_status_display()} تغییر کرد', f'سفارش شما به {instance.get_status_display()} تغییر کرد', ProductImageModel.objects.all().first().image.url)
- except:
- print('log later send notif error')
-
-
-def send_change_status_sms(instance):
- sms_api = ghasedak_sms.Ghasedak(api_key="1227eaaddcba72bcb0169b37032cf16ae9ac6ed8b3b7c2768b74e2ee351d1b52gyRe3AGomZRPTNEd")
-
-
- response = sms_api.send_single_sms(
- ghasedak_sms.SendSingleSmsInput(
- message=f'سفارش شما به {instance.get_status_display()} تغییر کرد',
- receptor=instance.user.phone,
- line_number='30005006004095',
- client_reference_id=str(instance.user.pk)
- )
- )
- if response['statusCode'] == 200:
- print('done log later')
- else:
- print(f'error: {response}')
def update_cart_price_fields(order):
diff --git a/backend/order/tasks.py b/backend/order/tasks.py
index e1449c3..1a87f1e 100644
--- a/backend/order/tasks.py
+++ b/backend/order/tasks.py
@@ -4,7 +4,9 @@ from azbankgateways import (
models as bank_models,
default_settings as settings,
)
-
+from .models import OrderModel
+from account.models import PushSubscription
+import ghasedak_sms
from celery import shared_task
@@ -23,4 +25,34 @@ def udpate_bank_status():
if bank_record.is_success:
logging.debug("This record is verify now.", extra={"pk": bank_record.pk})
- print('update bank record is done')
\ No newline at end of file
+ return 'update bank record is done'
+
+
+@shared_task
+def send_change_status_notif(instance_pk, new_status):
+ instance = OrderModel.objects.get(pk=instance_pk)
+ user_subs = PushSubscription.objects.filter(user=instance.user)
+ for user_sub in user_subs:
+ try:
+ user_sub.send_notif(f'سفارش شما به {new_status} تغییر کرد', f'سفارش شما به {new_status} تغییر کرد', ProductImageModel.objects.all().first().image.url)
+ except:
+ print('log later send notif error')
+
+@shared_task
+def send_change_status_sms(instance_pk, new_status):
+ instance = OrderModel.objects.get(pk=instance_pk)
+ sms_api = ghasedak_sms.Ghasedak(api_key="1227eaaddcba72bcb0169b37032cf16ae9ac6ed8b3b7c2768b74e2ee351d1b52gyRe3AGomZRPTNEd")
+
+
+ response = sms_api.send_single_sms(
+ ghasedak_sms.SendSingleSmsInput(
+ message=f'سفارش شما به {new_status} تغییر کرد',
+ receptor=instance.user.phone,
+ line_number='30005006004095',
+ client_reference_id=str(instance.user.pk)
+ )
+ )
+ if response['statusCode'] == 200:
+ return 'done log later'
+ else:
+ return f'error: {response}'
\ No newline at end of file
diff --git a/backend/order/views.py b/backend/order/views.py
index 19a01ee..335c647 100644
--- a/backend/order/views.py
+++ b/backend/order/views.py
@@ -197,7 +197,7 @@ class OrderGetView(APIView):
from rest_framework import serializers
class BankTypeSerializer(serializers.Serializer):
- gateway_type = serializers.ChoiceField(choices=['BMI', 'SEP', 'ZARINPAL', 'IDPAY', 'ZIBAL', 'BAHAMTA', 'MELLAT', 'PAYV1'])
+ gateway_type = serializers.ChoiceField(choices=['ZIBAL', 'BMI', 'SEP', 'ZARINPAL', 'IDPAY', 'BAHAMTA', 'MELLAT', 'PAYV1'])
class PaymentView(APIView):
@@ -210,18 +210,19 @@ class PaymentView(APIView):
def post(self, request):
print(request.data.get('gateway_type'))
cart_order = get_object_or_404(OrderModel, user=request.user, status='CART')
- amount = 5000
+ amount = 10000
user_mobile_number = request.user.phone
factory = bankfactories.BankFactory()
try:
bank = (
- factory.auto_create()
+ factory.create(
+ bank_models.BankType.ZIBAL
+ )
)
bank.set_request(request)
bank.set_amount(amount)
-
- bank.set_client_callback_url(request.build_absolute_uri(reverse("callback-gateway")))
+ bank.set_client_callback_url(reverse("callback-gateway"))
print(reverse('callback-gateway'))
bank.set_mobile_number(user_mobile_number)
@@ -230,7 +231,7 @@ class PaymentView(APIView):
# cart_order.save()
bank_record.order = cart_order
bank_record.save()
- return Response(bank.redirect_gateway().url)
+ return Response(bank.get_gateway())
except AZBankGatewaysException as e:
print(e)
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
diff --git a/backend/product/migrations/0035_alter_attributetype_options_and_more.py b/backend/product/migrations/0035_alter_attributetype_options_and_more.py
new file mode 100644
index 0000000..d426fc7
--- /dev/null
+++ b/backend/product/migrations/0035_alter_attributetype_options_and_more.py
@@ -0,0 +1,26 @@
+# Generated by Django 5.1.2 on 2025-03-28 15:39
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('product', '0034_remove_productvariant_max_price_and_more'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='attributetype',
+ options={'verbose_name': 'نوع متغییر محصول', 'verbose_name_plural': 'نوع های متغییر محصول'},
+ ),
+ migrations.AlterModelOptions(
+ name='attributevalue',
+ options={'verbose_name': 'مقدار متغییر محصول', 'verbose_name_plural': 'مقدار های متغییر محصول'},
+ ),
+ migrations.AlterField(
+ model_name='attributetype',
+ name='name',
+ field=models.CharField(max_length=100, verbose_name='نام نوع متغییر'),
+ ),
+ ]
diff --git a/backend/ticket/migrations/0019_alter_attachment_options.py b/backend/ticket/migrations/0019_alter_attachment_options.py
new file mode 100644
index 0000000..14a4e78
--- /dev/null
+++ b/backend/ticket/migrations/0019_alter_attachment_options.py
@@ -0,0 +1,17 @@
+# Generated by Django 5.1.2 on 2025-03-28 15:39
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('ticket', '0018_alter_ticket_created_at_alter_ticket_updated_at'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='attachment',
+ options={'verbose_name': 'پیوست تیکت', 'verbose_name_plural': 'پیوست های تیکت'},
+ ),
+ ]
diff --git a/docker-compose.yml b/docker-compose.yml
index 756bfc3..577d9f1 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -10,9 +10,10 @@ services:
networks:
- default
environment:
- - API_BASE_URL="https://api.heymlz.com"
- - DEBUG="false"
- - NUXT_IMAGE_DOMAINS="https://c262408.parspack.net"
+ - API_BASE_URL=https://api.heymlz.com
+ - DEBUG=false
+ - NUXT_IMAGE_DOMAINS=https://c262408.parspack.net
+ restart: always
django:
container_name: shop_backend
@@ -28,6 +29,7 @@ services:
- media_data:/app/static
networks:
- default
+ restart: always
db:
container_name: shop_db
@@ -42,6 +44,7 @@ services:
- "5434:5432"
networks:
- default
+ restart: always
db-backup:
container_name: shop_backup
@@ -62,6 +65,7 @@ services:
- backups:/backups
networks:
- default
+ restart: always
redis:
@@ -71,6 +75,7 @@ services:
- "6379:6379"
networks:
- default
+ restart: always
celery_worker:
container_name: shop_celery_worker
@@ -86,6 +91,7 @@ services:
- CELERY_BROKER_URL=redis://redis:6379/0
networks:
- default
+ restart: always
celery_beat:
container_name: shop_celery_beat
@@ -101,6 +107,7 @@ services:
- CELERY_BROKER_URL=redis://redis:6379/0
networks:
- default
+ restart: always
volumes: