from datetime import date from types import SimpleNamespace from unittest.mock import MagicMock, patch from django.test import SimpleTestCase from apps.wpm.views import MlogbInViewSet class GenNumberWithRuleFilterTests(SimpleTestCase): def test_date_filters_follow_rule_placeholders(self): cases = [ ("SN-{n_count:04d}", {}), ("{c_year}-{n_count:04d}", {"year": 2026}), ("{c_year2}-{n_count:04d}", {"year": 2026}), ("{c_month:02d}-{n_count:04d}", {"month": 8}), ("{c_day:02d}-{n_count:04d}", {"day": 4}), ( "{c_year}{c_month:02d}{c_day:02d}-{n_count:04d}", {"year": 2026, "month": 8, "day": 4}, ), ] material = SimpleNamespace(model=None) mlog = SimpleNamespace( handle_date=date(2026, 8, 4), mgroup=SimpleNamespace(process=SimpleNamespace(id=123)), ) for rule, expected_dates in cases: with self.subTest(rule=rule): queryset = MagicMock() queryset.values_list.return_value.distinct.return_value.iterator.return_value = [] with patch("apps.wpmw.models.Wpr.objects.filter", return_value=queryset) as mock_filter: MlogbInViewSet.gen_number_with_rule(rule, material, mlog) filters = mock_filter.call_args.kwargs date_prefix = "wpr_mlogbw__mlogb__mlog__handle_date__" actual_dates = { key.removeprefix(date_prefix): value for key, value in filters.items() if key.startswith(date_prefix) } self.assertEqual(actual_dates, expected_dates) def test_escaped_date_placeholder_text_does_not_add_filter(self): queryset = MagicMock() queryset.values_list.return_value.distinct.return_value.iterator.return_value = [] material = SimpleNamespace(model=None) mlog = SimpleNamespace( handle_date=date(2026, 8, 4), mgroup=SimpleNamespace(process=SimpleNamespace(id=123)), ) with patch("apps.wpmw.models.Wpr.objects.filter", return_value=queryset) as mock_filter: MlogbInViewSet.gen_number_with_rule("{{c_year}}-{n_count:04d}", material, mlog) self.assertFalse( any("handle_date" in key for key in mock_filter.call_args.kwargs) ) def test_previous_sequence_width_is_compatible(self): queryset = MagicMock() queryset.values_list.return_value.distinct.return_value.iterator.return_value = [ "2608P0001", "2608P0003", "2608P0002", ] material = SimpleNamespace(model="P") mlog = SimpleNamespace( handle_date=date(2026, 8, 6), mgroup=SimpleNamespace(process=SimpleNamespace(id=123)), ) with patch("apps.wpmw.models.Wpr.objects.filter", return_value=queryset): number = MlogbInViewSet.gen_number_with_rule( "{c_year2}{c_month:02d}{m_model}{n_count:05d}", material, mlog, ) self.assertEqual(number, "2608P00004") def test_mixed_sequence_widths_use_numeric_maximum(self): queryset = MagicMock() queryset.values_list.return_value.distinct.return_value.iterator.return_value = [ "2608P9999", "2608P10000", "历史异常编号", ] material = SimpleNamespace(model="P") mlog = SimpleNamespace( handle_date=date(2026, 8, 6), mgroup=SimpleNamespace(process=SimpleNamespace(id=123)), ) with patch("apps.wpmw.models.Wpr.objects.filter", return_value=queryset): number = MlogbInViewSet.gen_number_with_rule( "{c_year2}{c_month:02d}{m_model}{n_count:05d}", material, mlog, ) self.assertEqual(number, "2608P10001") def test_unrelated_historical_formats_do_not_participate(self): queryset = MagicMock() queryset.values_list.return_value.distinct.return_value.iterator.return_value = [ "202505508001", "3p05013", "05002", "3pb003", ] material = SimpleNamespace(model="P") mlog = SimpleNamespace( handle_date=date(2026, 8, 7), mgroup=SimpleNamespace(process=SimpleNamespace(id=123)), ) with patch("apps.wpmw.models.Wpr.objects.filter", return_value=queryset): number = MlogbInViewSet.gen_number_with_rule( "{m_model}{n_count:04d}", material, mlog, ) self.assertEqual(number, "P0001") def test_current_rule_uses_only_matching_model_numbers(self): queryset = MagicMock() queryset.values_list.return_value.distinct.return_value.iterator.return_value = [ "P0002", "P0010", "B0099", "3pb100", ] material = SimpleNamespace(model="P") mlog = SimpleNamespace( handle_date=date(2026, 8, 7), mgroup=SimpleNamespace(process=SimpleNamespace(id=123)), ) with patch("apps.wpmw.models.Wpr.objects.filter", return_value=queryset): number = MlogbInViewSet.gen_number_with_rule( "{m_model}{n_count:04d}", material, mlog, ) self.assertEqual(number, "P0011") def test_empty_historical_number_is_ignored(self): queryset = MagicMock() queryset.values_list.return_value.distinct.return_value.iterator.return_value = [ None, "", "P0002", ] material = SimpleNamespace(model="P") mlog = SimpleNamespace( handle_date=date(2026, 8, 7), mgroup=SimpleNamespace(process=SimpleNamespace(id=123)), ) with patch("apps.wpmw.models.Wpr.objects.filter", return_value=queryset): number = MlogbInViewSet.gen_number_with_rule( "{m_model}{n_count:04d}", material, mlog, ) self.assertEqual(number, "P0003") def test_repeated_sequence_placeholder_does_not_break_matching(self): queryset = MagicMock() queryset.values_list.return_value.distinct.return_value.iterator.return_value = [ "P02-0002", "P03-0004", ] material = SimpleNamespace(model="P") mlog = SimpleNamespace( handle_date=date(2026, 8, 7), mgroup=SimpleNamespace(process=SimpleNamespace(id=123)), ) with patch("apps.wpmw.models.Wpr.objects.filter", return_value=queryset): number = MlogbInViewSet.gen_number_with_rule( "{m_model}{n_count:02d}-{n_count:04d}", material, mlog, ) self.assertEqual(number, "P03-0003")