108 lines
5.2 KiB
Python
108 lines
5.2 KiB
Python
"""Supplier creation requires a manually supplied supplier code."""
|
|
from pathlib import Path
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from app import app
|
|
from routes import products
|
|
|
|
|
|
class SupplierManualCodeTest(unittest.TestCase):
|
|
def create(self, data, existing=None):
|
|
with app.test_request_context('/api/supplier/create', method='POST', json=data), \
|
|
patch.object(products, 'operation_required', return_value=True), \
|
|
patch.object(products, 'query', return_value=existing or []) as query, \
|
|
patch.object(products, 'add_operation_log'):
|
|
result = products.supplier_create.__wrapped__()
|
|
return result.get_json(), query
|
|
|
|
def test_manually_supplied_code_is_saved_without_contract_short_name(self):
|
|
payload, query = self.create({
|
|
'supplier_code': 'SUP-001',
|
|
'supplier_name': '测试供应商',
|
|
})
|
|
self.assertEqual(payload['code'], 0)
|
|
insert = next(call for call in query.call_args_list if 'INSERT INTO suppliers' in call.args[0])
|
|
self.assertEqual(insert.args[1][:2], ('SUP-001', '测试供应商'))
|
|
self.assertEqual(payload['data']['supplier_code'], 'SUP-001')
|
|
|
|
def test_code_is_required(self):
|
|
payload, query = self.create({'supplier_name': '测试供应商'})
|
|
self.assertEqual(payload['code'], 400)
|
|
self.assertIn('供应商编码不能为空', payload['msg'])
|
|
query.assert_not_called()
|
|
|
|
def test_duplicate_code_is_rejected(self):
|
|
payload, query = self.create(
|
|
{'supplier_code': 'SUP-001', 'supplier_name': '测试供应商'},
|
|
existing=[{'id': 12}],
|
|
)
|
|
self.assertEqual(payload['code'], 400)
|
|
self.assertIn('已存在', payload['msg'])
|
|
self.assertEqual(query.call_count, 1)
|
|
self.assertFalse(any('INSERT INTO suppliers' in call.args[0] for call in query.call_args_list))
|
|
|
|
def test_contract_short_name_remains_optional_and_uppercase_when_present(self):
|
|
payload, _ = self.create({
|
|
'supplier_code': 'SUP-002',
|
|
'supplier_name': '测试供应商',
|
|
'contract_short_name': 'ABC',
|
|
})
|
|
self.assertEqual(payload['code'], 0)
|
|
invalid, query = self.create({
|
|
'supplier_code': 'SUP-003',
|
|
'supplier_name': '测试供应商',
|
|
'contract_short_name': 'abc',
|
|
})
|
|
self.assertEqual(invalid['code'], 400)
|
|
query.assert_not_called()
|
|
|
|
def test_frontend_asks_for_manual_code(self):
|
|
source = (Path(__file__).resolve().parents[1] / 'static/js/app.js').read_text(encoding='utf-8')
|
|
self.assertIn('id="newSupCode"', source)
|
|
self.assertIn('supplier_code: code', source)
|
|
self.assertNotIn('供应商编码由系统自动生成', source)
|
|
self.assertNotIn('CGHTDY-合同简称-生成日期-6位随机码', source)
|
|
|
|
def test_edit_modal_exposes_supplier_code(self):
|
|
source = (Path(__file__).resolve().parents[1] / 'static/js/app.js').read_text(encoding='utf-8')
|
|
self.assertIn("{label:'供应商编码', id:'es_code', val:s.supplier_code || code, type:'text'}", source)
|
|
self.assertIn("supplier_code: newCode", source)
|
|
|
|
def test_code_change_updates_supplier_and_live_references_transactionally(self):
|
|
from unittest.mock import MagicMock
|
|
conn = MagicMock()
|
|
cur = conn.cursor.return_value.__enter__.return_value
|
|
cur.fetchone.side_effect = [{'id': 4}, None]
|
|
with app.test_request_context('/api/supplier/update', method='POST', json={
|
|
'supplier_code': 'OLD', 'fields': {'supplier_code': 'NEW', 'supplier_name': '供应商'}
|
|
}), patch.object(products, 'operation_required', return_value=True), \
|
|
patch.object(products, 'get_db', return_value=conn), \
|
|
patch.object(products, 'add_operation_log'):
|
|
response = products.supplier_update.__wrapped__().get_json()
|
|
self.assertEqual(response['code'], 0)
|
|
updates = [call.args for call in cur.execute.call_args_list]
|
|
self.assertIn(('UPDATE products SET supplier_code=%s WHERE supplier_code=%s', ('NEW', 'OLD')), updates)
|
|
self.assertIn(('UPDATE new_product_bom SET supplier_code=%s WHERE supplier_code=%s', ('NEW', 'OLD')), updates)
|
|
conn.commit.assert_called_once()
|
|
conn.close.assert_called_once()
|
|
|
|
def test_edit_rejects_duplicate_supplier_code_without_updates(self):
|
|
from unittest.mock import MagicMock
|
|
conn = MagicMock()
|
|
cur = conn.cursor.return_value.__enter__.return_value
|
|
cur.fetchone.side_effect = [{'id': 4}, {'id': 5}]
|
|
with app.test_request_context('/api/supplier/update', method='POST', json={
|
|
'supplier_code': 'OLD', 'fields': {'supplier_code': 'USED'}
|
|
}), patch.object(products, 'operation_required', return_value=True), \
|
|
patch.object(products, 'get_db', return_value=conn):
|
|
response = products.supplier_update.__wrapped__()
|
|
self.assertEqual(response.get_json()['code'], 400)
|
|
self.assertEqual(cur.execute.call_count, 2)
|
|
conn.rollback.assert_called_once()
|
|
conn.commit.assert_not_called()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|