fix(wpm): derive number date filters from rule
This commit is contained in:
parent
19271e8880
commit
ddb3cc6f3f
|
|
@ -0,0 +1,64 @@
|
||||||
|
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.annotate.return_value = queryset
|
||||||
|
queryset.order_by.return_value = queryset
|
||||||
|
queryset.last.return_value = None
|
||||||
|
|
||||||
|
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.annotate.return_value = queryset
|
||||||
|
queryset.order_by.return_value = queryset
|
||||||
|
queryset.last.return_value = None
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import math
|
import math
|
||||||
import re
|
import re
|
||||||
|
from string import Formatter
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
|
|
@ -1010,13 +1011,18 @@ class MlogbInViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, BulkDestroyMode
|
||||||
def gen_number_with_rule(cls, rule, material_out: Material, mlog: Mlog, gen_count=1):
|
def gen_number_with_rule(cls, rule, material_out: Material, mlog: Mlog, gen_count=1):
|
||||||
from apps.wpmw.models import Wpr
|
from apps.wpmw.models import Wpr
|
||||||
|
|
||||||
|
rule_fields = {
|
||||||
|
field_name
|
||||||
|
for _, field_name, _, _ in Formatter().parse(rule)
|
||||||
|
if field_name
|
||||||
|
}
|
||||||
handle_date = mlog.handle_date
|
handle_date = mlog.handle_date
|
||||||
c_year = handle_date.year
|
c_year = handle_date.year
|
||||||
c_year2 = str(c_year)[-2:]
|
c_year2 = str(c_year)[-2:]
|
||||||
c_month = handle_date.month
|
c_month = handle_date.month
|
||||||
c_day = handle_date.day
|
c_day = handle_date.day
|
||||||
m_model = material_out.model
|
m_model = material_out.model
|
||||||
if 'm_model' in rule:
|
if "m_model" in rule_fields:
|
||||||
if m_model is None:
|
if m_model is None:
|
||||||
raise ParseError("生成编号出错:产品型号不能为空")
|
raise ParseError("生成编号出错:产品型号不能为空")
|
||||||
elif m_model and m_model.islower():
|
elif m_model and m_model.islower():
|
||||||
|
|
@ -1029,16 +1035,18 @@ class MlogbInViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, BulkDestroyMode
|
||||||
if connection.vendor == "postgresql" and connection.in_atomic_block:
|
if connection.vendor == "postgresql" and connection.in_atomic_block:
|
||||||
with connection.cursor() as cursor:
|
with connection.cursor() as cursor:
|
||||||
cursor.execute("SELECT pg_advisory_xact_lock(hashtextextended(%s, 0))", [f"wpr_number_rule:{process.id}"])
|
cursor.execute("SELECT pg_advisory_xact_lock(hashtextextended(%s, 0))", [f"wpr_number_rule:{process.id}"])
|
||||||
# 按生产日志查询, 流水号归零周期跟随规则中最细的日期占位符
|
# 只按规则中实际使用的日期占位符筛选历史编号
|
||||||
wpr_filter = {
|
wpr_filter = {
|
||||||
"wpr_mlogbw__mlogb__material_out__isnull": False,
|
"wpr_mlogbw__mlogb__material_out__isnull": False,
|
||||||
"wpr_mlogbw__mlogb__mlog__mgroup__process": process,
|
"wpr_mlogbw__mlogb__mlog__mgroup__process": process,
|
||||||
"wpr_mlogbw__mlogb__mlog__is_fix": False,
|
"wpr_mlogbw__mlogb__mlog__is_fix": False,
|
||||||
"wpr_mlogbw__mlogb__mlog__submit_time__isnull": False,
|
"wpr_mlogbw__mlogb__mlog__submit_time__isnull": False,
|
||||||
"wpr_mlogbw__mlogb__mlog__handle_date__year": c_year,
|
|
||||||
"wpr_mlogbw__mlogb__mlog__handle_date__month": c_month,
|
|
||||||
}
|
}
|
||||||
if "c_day" in rule:
|
if rule_fields & {"c_year", "c_year2"}:
|
||||||
|
wpr_filter["wpr_mlogbw__mlogb__mlog__handle_date__year"] = c_year
|
||||||
|
if "c_month" in rule_fields:
|
||||||
|
wpr_filter["wpr_mlogbw__mlogb__mlog__handle_date__month"] = c_month
|
||||||
|
if "c_day" in rule_fields:
|
||||||
wpr_filter["wpr_mlogbw__mlogb__mlog__handle_date__day"] = c_day
|
wpr_filter["wpr_mlogbw__mlogb__mlog__handle_date__day"] = c_day
|
||||||
wpr = (
|
wpr = (
|
||||||
Wpr.objects.filter(**wpr_filter)
|
Wpr.objects.filter(**wpr_filter)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue