All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 2m8s
307 lines
11 KiB
Python
307 lines
11 KiB
Python
import os
|
|
import sys
|
|
from unittest.mock import MagicMock
|
|
|
|
# Mock celery before importing settings
|
|
sys.modules['celery'] = MagicMock()
|
|
sys.modules['celery.schedules'] = MagicMock()
|
|
sys.modules['django_celery_beat'] = MagicMock()
|
|
sys.modules['drf_spectacular'] = MagicMock()
|
|
sys.modules['drf_spectacular.extensions'] = MagicMock()
|
|
|
|
sys.path.insert(0, 'D:/Tradhox_workspace/Django-CRM/backend')
|
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'crm.settings'
|
|
|
|
import django
|
|
from django.conf import settings
|
|
|
|
# Override settings for standalone unit test
|
|
settings.DATABASES = {
|
|
'default': {
|
|
'ENGINE': 'django.db.backends.sqlite3',
|
|
'NAME': ':memory:',
|
|
},
|
|
'seller_db': {
|
|
'ENGINE': 'django.db.backends.sqlite3',
|
|
'NAME': ':memory:',
|
|
},
|
|
'product_db': {
|
|
'ENGINE': 'django.db.backends.sqlite3',
|
|
'NAME': ':memory:',
|
|
},
|
|
'customer_db': {
|
|
'ENGINE': 'django.db.backends.sqlite3',
|
|
'NAME': ':memory:',
|
|
},
|
|
}
|
|
settings.REST_FRAMEWORK = {
|
|
'DEFAULT_AUTHENTICATION_CLASSES': [],
|
|
'DEFAULT_PERMISSION_CLASSES': [],
|
|
}
|
|
settings.DATABASE_ROUTERS = ['crm.db_router.CRMDatabaseRouter']
|
|
settings.AUTH_USER_MODEL = 'auth.User'
|
|
settings.INSTALLED_APPS = [
|
|
'django.contrib.contenttypes',
|
|
'django.contrib.auth',
|
|
'rest_framework',
|
|
'sellers',
|
|
]
|
|
|
|
django.setup()
|
|
|
|
from sellers.models import SupplierProfile, Product, BulkUploadLog, SellerOrder, Wallet
|
|
from sellers.serializers import (
|
|
SupplierProfileListSerializer,
|
|
SupplierProfileDetailSerializer,
|
|
ProductSerializer
|
|
)
|
|
from crm.db_router import CRMDatabaseRouter
|
|
|
|
# 1. Test Router mappings
|
|
router = CRMDatabaseRouter()
|
|
assert router.db_for_read(Product) == 'product_db', f"Product should route to product_db, got {router.db_for_read(Product)}"
|
|
assert router.db_for_read(BulkUploadLog) == 'product_db', f"BulkUploadLog should route to product_db, got {router.db_for_read(BulkUploadLog)}"
|
|
assert router.db_for_read(SellerOrder) == 'customer_db', f"SellerOrder should route to customer_db, got {router.db_for_read(SellerOrder)}"
|
|
assert router.db_for_read(Wallet) == 'customer_db', f"Wallet should route to customer_db, got {router.db_for_read(Wallet)}"
|
|
assert router.db_for_read(SupplierProfile) == 'seller_db', f"SupplierProfile should route to seller_db, got {router.db_for_read(SupplierProfile)}"
|
|
print("CRMDatabaseRouter checks passed!")
|
|
|
|
# 2. Create tables in test DBs
|
|
from django.db import connections
|
|
|
|
def create_table_product():
|
|
with connections['product_db'].cursor() as c:
|
|
c.execute("""
|
|
CREATE TABLE api_product (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
supplier_id INTEGER,
|
|
title VARCHAR(255),
|
|
category VARCHAR(100),
|
|
price DECIMAL(10, 2),
|
|
stock INTEGER,
|
|
sku VARCHAR(100),
|
|
image TEXT,
|
|
is_active BOOLEAN,
|
|
status VARCHAR(50),
|
|
compare_at_price DECIMAL(10, 2),
|
|
description TEXT,
|
|
is_gi_tagged BOOLEAN,
|
|
gi_tag_name VARCHAR(200),
|
|
is_odop BOOLEAN,
|
|
odop_district VARCHAR(200),
|
|
is_sustainable BOOLEAN,
|
|
sustainable_type VARCHAR(200),
|
|
geographical_origin VARCHAR(255),
|
|
statutory_certifications TEXT,
|
|
provenance_story TEXT,
|
|
coordinates VARCHAR(100),
|
|
track_inventory BOOLEAN,
|
|
shipping_profile VARCHAR(100),
|
|
processing_days INTEGER,
|
|
package_weight REAL,
|
|
upload_source VARCHAR(50),
|
|
rejection_reason TEXT,
|
|
additional_images TEXT,
|
|
video_url VARCHAR(200),
|
|
view_360_url VARCHAR(200)
|
|
)
|
|
""")
|
|
|
|
def create_table_seller():
|
|
with connections['seller_db'].cursor() as c:
|
|
c.execute("""
|
|
CREATE TABLE api_supplierprofile (
|
|
id INTEGER PRIMARY KEY,
|
|
user_id INTEGER UNIQUE,
|
|
phone VARCHAR(20),
|
|
phone_verified BOOLEAN,
|
|
email_verified BOOLEAN,
|
|
gstin VARCHAR(15),
|
|
is_gstin_verified BOOLEAN,
|
|
pan_number VARCHAR(20),
|
|
is_pan_verified BOOLEAN,
|
|
verified_pan_name VARCHAR(255),
|
|
verified_gst_name VARCHAR(255),
|
|
is_verified BOOLEAN,
|
|
business_type VARCHAR(50),
|
|
store_slug VARCHAR(255),
|
|
aadhar_file VARCHAR(255),
|
|
pan_file VARCHAR(255),
|
|
aadhar_s3_key VARCHAR(255),
|
|
pan_s3_key VARCHAR(255),
|
|
store_name VARCHAR(255),
|
|
store_logo TEXT,
|
|
logo_s3_key VARCHAR(255),
|
|
business_bio TEXT,
|
|
street VARCHAR(255),
|
|
city VARCHAR(100),
|
|
state VARCHAR(100),
|
|
pincode VARCHAR(20),
|
|
latitude REAL,
|
|
longitude REAL,
|
|
status VARCHAR(50),
|
|
submitted_at DATETIME,
|
|
approved_at DATETIME,
|
|
approved_by VARCHAR(150),
|
|
rejected_reason TEXT,
|
|
is_profile_complete BOOLEAN,
|
|
pickup_code VARCHAR(100),
|
|
account_holder_name VARCHAR(255),
|
|
account_number VARCHAR(50),
|
|
ifsc_code VARCHAR(20),
|
|
bank_name VARCHAR(255),
|
|
is_bank_verified BOOLEAN,
|
|
tax_mode VARCHAR(20)
|
|
)
|
|
""")
|
|
|
|
def create_table_customer():
|
|
with connections['customer_db'].cursor() as c:
|
|
c.execute("""
|
|
CREATE TABLE api_order (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
order_id VARCHAR(100),
|
|
customer VARCHAR(255),
|
|
item VARCHAR(255),
|
|
quantity INTEGER,
|
|
total DECIMAL(12, 2),
|
|
status VARCHAR(50),
|
|
carrier VARCHAR(100),
|
|
tracking VARCHAR(100),
|
|
date DATE,
|
|
supplier_id INTEGER,
|
|
payment_mode VARCHAR(20),
|
|
eta VARCHAR(50),
|
|
expected_delivery_date VARCHAR(100),
|
|
pickup_id VARCHAR(100),
|
|
pickup_payload TEXT
|
|
)
|
|
""")
|
|
c.execute("""
|
|
CREATE TABLE api_wallet (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
supplier_id INTEGER UNIQUE,
|
|
outstanding DECIMAL(12, 2),
|
|
withdrawn DECIMAL(12, 2)
|
|
)
|
|
""")
|
|
|
|
create_table_product()
|
|
create_table_seller()
|
|
create_table_customer()
|
|
|
|
# Create SupplierProfile with id=46, user_id=28
|
|
seller = SupplierProfile.objects.create(
|
|
id=46,
|
|
user_id=28,
|
|
store_name="vignesh store",
|
|
phone="9600494039",
|
|
status="approved"
|
|
)
|
|
|
|
# Create Product with supplier_id=28 (which is seller.user_id)
|
|
product = Product.objects.create(
|
|
id=20,
|
|
supplier_id=28,
|
|
title="Pure Kanchipuram Mulberry Silk Saree - Crimson Maroon & Gold Zari",
|
|
category="Clothing & Textiles",
|
|
price=14500.00,
|
|
stock=8,
|
|
sku="TRDX-KSS-960049",
|
|
is_gi_tagged=True,
|
|
gi_tag_name="Kancheepuram Silk (GI Application #26)",
|
|
is_odop=True,
|
|
odop_district="Kanchipuram, Tamil Nadu",
|
|
is_sustainable=True,
|
|
sustainable_type="Handloom Organic Mulberry Silk & Eco-dyes",
|
|
geographical_origin="Kanchipuram, Tamil Nadu, India",
|
|
statutory_certifications="GI Tag #26 Registered, Silk Mark Certified, Handloom Mark India",
|
|
status="pending",
|
|
is_active=True
|
|
)
|
|
|
|
# Test SupplierProfileListSerializer
|
|
list_data = SupplierProfileListSerializer(seller).data
|
|
print(f"SupplierProfileListSerializer products_count: {list_data['products_count']}")
|
|
assert list_data['products_count'] == 1, f"Expected products_count 1, got {list_data['products_count']}"
|
|
|
|
# Test SupplierProfileDetailSerializer
|
|
detail_data = SupplierProfileDetailSerializer(seller).data
|
|
print(f"Detail metrics: {detail_data['metrics']}")
|
|
assert detail_data['metrics']['total_products'] == 1, f"Expected 1 total_products, got {detail_data['metrics']['total_products']}"
|
|
assert detail_data['metrics']['total_items_in_stock'] == 8, f"Expected 8 items in stock, got {detail_data['metrics']['total_items_in_stock']}"
|
|
assert len(detail_data['products']) == 1, f"Expected 1 product in products list, got {len(detail_data['products'])}"
|
|
|
|
prod_data = detail_data['products'][0]
|
|
print(f"Product in detail: ID={prod_data['id']}, title='{prod_data['title']}', is_gi_tagged={prod_data['is_gi_tagged']}, is_odop={prod_data['is_odop']}, is_sustainable={prod_data['is_sustainable']}")
|
|
assert prod_data['id'] == 20
|
|
assert prod_data['is_gi_tagged'] is True
|
|
assert prod_data['is_odop'] is True
|
|
assert prod_data['is_sustainable'] is True
|
|
|
|
print("ALL SERIALIZER AND MODEL TESTS PASSED SUCCESSFULLY!")
|
|
|
|
# 3. Test Views logic (Approve, Reject, Toggle, Edit Content)
|
|
from sellers.views import (
|
|
SellerProductApproveView,
|
|
SellerProductRejectView,
|
|
SellerProductToggleView,
|
|
SellerProductDetailView
|
|
)
|
|
from django.core.management import call_command
|
|
call_command('migrate', database='default', run_syncdb=True, verbosity=0)
|
|
from rest_framework.test import APIRequestFactory, force_authenticate
|
|
from django.contrib.auth.models import User
|
|
|
|
factory = APIRequestFactory()
|
|
admin_user = User.objects.create_user(username='admin', email='admin@tradhox.com')
|
|
|
|
# Test Approve
|
|
req = factory.post(f"/api/sellers/46/products/20/approve/")
|
|
force_authenticate(req, user=admin_user)
|
|
resp = SellerProductApproveView.as_view()(req, pk=46, product_id=20)
|
|
assert resp.status_code == 200, f"Expected 200, got {resp.status_code}: {resp.data}"
|
|
p = Product.objects.using('product_db').get(pk=20)
|
|
assert p.status == 'approved'
|
|
assert p.is_active is True
|
|
print("SellerProductApproveView passed!")
|
|
|
|
# Test Reject
|
|
req = factory.post(f"/api/sellers/46/products/20/reject/", {"reason": "Quality check required"}, format="json")
|
|
force_authenticate(req, user=admin_user)
|
|
resp = SellerProductRejectView.as_view()(req, pk=46, product_id=20)
|
|
assert resp.status_code == 200
|
|
p = Product.objects.using('product_db').get(pk=20)
|
|
assert p.status == 'rejected'
|
|
assert p.is_active is False
|
|
assert p.rejection_reason == "Quality check required"
|
|
print("SellerProductRejectView passed!")
|
|
|
|
# Test Toggle
|
|
req = factory.post(f"/api/sellers/46/products/20/toggle/", {"is_active": True, "status": "approved"}, format="json")
|
|
force_authenticate(req, user=admin_user)
|
|
resp = SellerProductToggleView.as_view()(req, pk=46, product_id=20)
|
|
assert resp.status_code == 200
|
|
p = Product.objects.using('product_db').get(pk=20)
|
|
assert p.is_active is True
|
|
assert p.status == 'approved'
|
|
print("SellerProductToggleView passed!")
|
|
|
|
# Test Detail PATCH
|
|
req = factory.patch(f"/api/sellers/46/products/20/", {
|
|
"price": 15200.00,
|
|
"stock": 12,
|
|
"is_odop": True,
|
|
"odop_district": "Kanchipuram District",
|
|
"geographical_origin": "Kanchipuram, Tamil Nadu"
|
|
}, format="json")
|
|
force_authenticate(req, user=admin_user)
|
|
resp = SellerProductDetailView.as_view()(req, pk=46, product_id=20)
|
|
assert resp.status_code == 200
|
|
p = Product.objects.using('product_db').get(pk=20)
|
|
assert float(p.price) == 15200.00
|
|
assert p.stock == 12
|
|
assert p.odop_district == "Kanchipuram District"
|
|
print("SellerProductDetailView PATCH passed!")
|
|
|
|
print("ALL VIEWS AND API ENDPOINT TESTS PASSED SUCCESSFULLY!")
|