forked from erp-dev/erp
feat: completed
This commit is contained in:
145
cost/tests/test_models.py
Normal file
145
cost/tests/test_models.py
Normal file
@@ -0,0 +1,145 @@
|
||||
"""Cost 模块模型测试"""
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import IntegrityError
|
||||
from django.test import TestCase
|
||||
|
||||
from basic_info import models as basic_models
|
||||
from cost import models as cost_models
|
||||
|
||||
|
||||
class CostCategoryModelTests(TestCase):
|
||||
def setUp(self):
|
||||
self.merchant = basic_models.Merchant.objects.create(
|
||||
name='测试商户', type=basic_models.MerchantTypeEnum.STORE,
|
||||
)
|
||||
|
||||
def test_str_representation(self):
|
||||
cat = cost_models.CostCategory.objects.create(
|
||||
merchant=self.merchant, unique_key='electricity', name='电费',
|
||||
)
|
||||
self.assertEqual(str(cat), '电费 (electricity)')
|
||||
|
||||
def test_unique_together_merchant_key(self):
|
||||
"""同一商户 same unique_key 不可重复"""
|
||||
cost_models.CostCategory.objects.create(
|
||||
merchant=self.merchant, unique_key='electricity', name='电费',
|
||||
)
|
||||
with self.assertRaises(IntegrityError):
|
||||
cost_models.CostCategory.objects.create(
|
||||
merchant=self.merchant, unique_key='electricity', name='电费2',
|
||||
)
|
||||
|
||||
def test_different_merchants_same_key_allowed(self):
|
||||
"""不同商户 same unique_key 允许"""
|
||||
other = basic_models.Merchant.objects.create(
|
||||
name='其他商户', type=basic_models.MerchantTypeEnum.STORE,
|
||||
)
|
||||
cat1 = cost_models.CostCategory.objects.create(
|
||||
merchant=self.merchant, unique_key='electricity', name='电费',
|
||||
)
|
||||
cat2 = cost_models.CostCategory.objects.create(
|
||||
merchant=other, unique_key='electricity', name='电费',
|
||||
)
|
||||
self.assertNotEqual(cat1.id, cat2.id)
|
||||
|
||||
def test_parent_self_reference(self):
|
||||
"""父类目 self-FK"""
|
||||
parent = cost_models.CostCategory.objects.create(
|
||||
merchant=self.merchant, unique_key='utilities', name='公共事业',
|
||||
)
|
||||
child = cost_models.CostCategory.objects.create(
|
||||
merchant=self.merchant, unique_key='electricity', name='电费',
|
||||
parent=parent,
|
||||
)
|
||||
self.assertEqual(child.parent_id, parent.id)
|
||||
self.assertEqual(list(parent.children.all()), [child])
|
||||
|
||||
def test_description_nullable(self):
|
||||
cat = cost_models.CostCategory.objects.create(
|
||||
merchant=self.merchant, unique_key='key', name='name',
|
||||
)
|
||||
self.assertIsNone(cat.description)
|
||||
|
||||
def test_ordering_by_merchant_then_name(self):
|
||||
other = basic_models.Merchant.objects.create(
|
||||
name='其他商户', type=basic_models.MerchantTypeEnum.STORE,
|
||||
)
|
||||
cost_models.CostCategory.objects.create(
|
||||
merchant=self.merchant, unique_key='z', name='Z类目',
|
||||
)
|
||||
cost_models.CostCategory.objects.create(
|
||||
merchant=self.merchant, unique_key='a', name='A类目',
|
||||
)
|
||||
cost_models.CostCategory.objects.create(
|
||||
merchant=other, unique_key='m', name='M类目',
|
||||
)
|
||||
# ordering = ('merchant', 'name') — 同一个 merchant 内按 name 排序
|
||||
own = cost_models.CostCategory.objects.filter(merchant=self.merchant)
|
||||
own_names = [c.name for c in own]
|
||||
self.assertEqual(own_names, ['A类目', 'Z类目']) # name 升序
|
||||
|
||||
|
||||
class CostEntryModelTests(TestCase):
|
||||
def setUp(self):
|
||||
self.merchant = basic_models.Merchant.objects.create(
|
||||
name='测试商户', type=basic_models.MerchantTypeEnum.STORE,
|
||||
)
|
||||
self.category = cost_models.CostCategory.objects.create(
|
||||
merchant=self.merchant, unique_key='transport', name='运输费',
|
||||
)
|
||||
|
||||
def test_str_representation(self):
|
||||
entry = cost_models.CostEntry.objects.create(
|
||||
merchant=self.merchant,
|
||||
category=self.category,
|
||||
amount=Decimal('150.00'),
|
||||
occurred_at=date(2026, 6, 1),
|
||||
)
|
||||
self.assertIn('运输费', str(entry))
|
||||
self.assertIn('150.00', str(entry))
|
||||
|
||||
def test_default_ordering_by_occurred_at_desc(self):
|
||||
e1 = cost_models.CostEntry.objects.create(
|
||||
merchant=self.merchant, category=self.category,
|
||||
amount=Decimal('100.00'), occurred_at=date(2026, 6, 1),
|
||||
)
|
||||
e2 = cost_models.CostEntry.objects.create(
|
||||
merchant=self.merchant, category=self.category,
|
||||
amount=Decimal('200.00'), occurred_at=date(2026, 6, 10),
|
||||
)
|
||||
entries = list(cost_models.CostEntry.objects.all())
|
||||
self.assertEqual(entries[0].id, e2.id)
|
||||
self.assertEqual(entries[1].id, e1.id)
|
||||
|
||||
def test_operator_nullable(self):
|
||||
entry = cost_models.CostEntry.objects.create(
|
||||
merchant=self.merchant,
|
||||
category=self.category,
|
||||
amount=Decimal('100.00'),
|
||||
occurred_at=date(2026, 6, 1),
|
||||
operator=None,
|
||||
)
|
||||
self.assertIsNone(entry.operator_id)
|
||||
|
||||
def test_source_fields_nullable(self):
|
||||
entry = cost_models.CostEntry.objects.create(
|
||||
merchant=self.merchant,
|
||||
category=self.category,
|
||||
amount=Decimal('100.00'),
|
||||
occurred_at=date(2026, 6, 1),
|
||||
)
|
||||
self.assertIsNone(entry.source_module)
|
||||
self.assertIsNone(entry.source_id)
|
||||
|
||||
def test_image_fields_nullable(self):
|
||||
entry = cost_models.CostEntry.objects.create(
|
||||
merchant=self.merchant,
|
||||
category=self.category,
|
||||
amount=Decimal('100.00'),
|
||||
occurred_at=date(2026, 6, 1),
|
||||
)
|
||||
self.assertFalse(bool(entry.image1))
|
||||
self.assertFalse(bool(entry.image2))
|
||||
Reference in New Issue
Block a user