""" تست‌های قرارداد فاکتور: حذف نرم، محافظت از اسناد انبار و جریان ساخت فاکتور از ویو. """ import json from django.db.models import ProtectedError from django.test import TestCase from django.urls import reverse from admin_panel.models import (Article, Factor, FactorIteam, ProductInStore) from .factories import current_stock, make_customer, make_product, make_store, make_user, stock_in class FactorSoftDeleteTests(TestCase): def setUp(self): self.customer = make_customer('مشتری فاکتور') self.factor = Factor.objects.create( customer=self.customer, amount=250_000, pay_status='unpaid', FactorType='Nasb', PayType='naghd', ) def test_delete_is_soft(self): factor_id = self.factor.id self.factor.delete() # رکورد باید باقی بماند اما باطل شده باشد still_there = Factor.objects.get(id=factor_id) self.assertFalse(still_there.is_active) self.assertEqual(still_there.pay_status, 'cancell') def test_instore_transaction_protects_its_factor(self): store = make_store('انبار فاکتور') product = make_product('کالای فاکتور') ProductInStore.objects.create( StoreRoom=store, Product=product, factor=self.factor, s_in=0, s_out=1, desc='خروج فاکتور', movement_type=ProductInStore.MovementType.SALE, ) with self.assertRaises(ProtectedError): Factor.objects.filter(id=self.factor.id).delete() class NewFactor2ViewTests(TestCase): """ تست جریان اصلی ویو `newFactor2` (مسیر استاندارد ساخت فاکتور) که پس از تقسیم views.py به ماژول factors منتقل شده است. """ def setUp(self): self.user = make_user('factorUser', superuser=True) self.store = make_store('انبار فاکتور', owner=self.user) self.customer = make_customer('مشتری فاکتور') self.product = make_product('کالای فروش', price=1000) stock_in(self.store, self.product, 20) def test_new_factor2_creates_factor_article_and_stock_out(self): self.client.force_login(self.user) url = reverse('admin_panel:newFactor2', kwargs={'c_id': self.customer.id}) payload = { 'prdsList': json.dumps([ {'prd_id': self.product.id, 'prd_count': 3, 'price': 1000, 'garanty_Esh': '', 'product_name': self.product.product_name}, ]), 'PardakhtHa': json.dumps({'l_naghd': 3000}), 'FactorType': 'Nasb', 'FactorDesc': 'تست ساخت فاکتور', 'sarResidDate': '', } response = self.client.post(url, payload) self.assertIn(response.status_code, (200, 302), msg=f"status={response.status_code}") factor = Factor.objects.filter(customer=self.customer).order_by('-id').first() self.assertIsNotNone(factor, msg="فاکتور ساخته نشد.") self.assertEqual(factor.amount, 3000) self.assertEqual(FactorIteam.objects.filter(factor=factor).count(), 1) # از انبار به اندازه ۳ عدد کسر شده باشد self.assertEqual(current_stock(self.store, self.product), 17) # سند بدهی بابت فاکتور ثبت شده باشد self.assertTrue(Article.objects.filter(factor=factor, debit=3000).exists()) def test_new_factor2_rejects_oversell_without_creating_factor(self): self.client.force_login(self.user) url = reverse('admin_panel:newFactor2', kwargs={'c_id': self.customer.id}) payload = { 'prdsList': json.dumps([ {'prd_id': self.product.id, 'prd_count': 999, 'price': 1000, 'garanty_Esh': '', 'product_name': self.product.product_name}, ]), 'PardakhtHa': json.dumps({}), 'FactorType': 'Nasb', 'FactorDesc': '', 'sarResidDate': '', } response = self.client.post(url, payload) # ویو نباید خطای سرور بدهد و نباید فاکتور ناقص ثبت شود self.assertNotEqual(response.status_code, 500) self.assertEqual(Factor.objects.filter(customer=self.customer).count(), 0) self.assertEqual(current_stock(self.store, self.product), 20) def test_new_factor2_rejects_get(self): self.client.force_login(self.user) url = reverse('admin_panel:newFactor2', kwargs={'c_id': self.customer.id}) response = self.client.get(url) self.assertEqual(response.status_code, 400)