Restrict global inventory handovers
This commit is contained in:
parent
1700a58409
commit
8af19b8a9a
|
|
@ -0,0 +1,36 @@
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0135_mlog_stored_scope'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='handover',
|
||||||
|
name='send_dept',
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='handover_send_dept',
|
||||||
|
to='system.dept',
|
||||||
|
verbose_name='送料部门',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='handover',
|
||||||
|
name='recive_dept',
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='handover_recive_dept',
|
||||||
|
to='system.dept',
|
||||||
|
verbose_name='接收部门',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -698,7 +698,8 @@ class Handover(CommonADModel):
|
||||||
send_mgroup = models.ForeignKey(
|
send_mgroup = models.ForeignKey(
|
||||||
Mgroup, verbose_name='送料工段', on_delete=models.CASCADE, null=True, blank=True)
|
Mgroup, verbose_name='送料工段', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
send_dept = models.ForeignKey(
|
send_dept = models.ForeignKey(
|
||||||
Dept, verbose_name='送料部门', on_delete=models.CASCADE, related_name='handover_send_dept')
|
Dept, verbose_name='送料部门', on_delete=models.CASCADE, related_name='handover_send_dept',
|
||||||
|
null=True, blank=True)
|
||||||
batch = models.TextField('批次号', null=True, blank=True, db_index=True)
|
batch = models.TextField('批次号', null=True, blank=True, db_index=True)
|
||||||
material = models.ForeignKey(
|
material = models.ForeignKey(
|
||||||
Material, verbose_name='物料', on_delete=models.CASCADE, related_name='h_ma')
|
Material, verbose_name='物料', on_delete=models.CASCADE, related_name='h_ma')
|
||||||
|
|
@ -707,7 +708,8 @@ class Handover(CommonADModel):
|
||||||
count = models.DecimalField('送料数', default=0, max_digits=11, decimal_places=1)
|
count = models.DecimalField('送料数', default=0, max_digits=11, decimal_places=1)
|
||||||
count_eweight = models.FloatField('单数重量', default=0)
|
count_eweight = models.FloatField('单数重量', default=0)
|
||||||
recive_dept = models.ForeignKey(
|
recive_dept = models.ForeignKey(
|
||||||
Dept, verbose_name='接收部门', on_delete=models.CASCADE, related_name='handover_recive_dept')
|
Dept, verbose_name='接收部门', on_delete=models.CASCADE, related_name='handover_recive_dept',
|
||||||
|
null=True, blank=True)
|
||||||
recive_mgroup = models.ForeignKey(Mgroup, verbose_name='接收工段', on_delete=models.CASCADE, related_name='handover_recive_mgroup', null=True, blank=True)
|
recive_mgroup = models.ForeignKey(Mgroup, verbose_name='接收工段', on_delete=models.CASCADE, related_name='handover_recive_mgroup', null=True, blank=True)
|
||||||
recive_user = models.ForeignKey(
|
recive_user = models.ForeignKey(
|
||||||
User, verbose_name='接收人', on_delete=models.CASCADE, related_name='handover_recive_user', null=True, blank=True)
|
User, verbose_name='接收人', on_delete=models.CASCADE, related_name='handover_recive_user', null=True, blank=True)
|
||||||
|
|
|
||||||
|
|
@ -1301,20 +1301,62 @@ class HandoverSerializer(CustomModelSerializer):
|
||||||
raise ParseError('必须指定车间库存')
|
raise ParseError('必须指定车间库存')
|
||||||
attrs['material'] = wm.material
|
attrs['material'] = wm.material
|
||||||
attrs['send_dept'] = wm.belong_dept
|
attrs['send_dept'] = wm.belong_dept
|
||||||
if wm.mgroup:
|
|
||||||
attrs['send_mgroup'] = wm.mgroup
|
attrs['send_mgroup'] = wm.mgroup
|
||||||
|
is_global_source = wm.mgroup_id is None and wm.belong_dept_id is None
|
||||||
|
|
||||||
|
if (
|
||||||
|
is_global_source
|
||||||
|
and attrs['type'] == Handover.H_NORMAL
|
||||||
|
and mtype == Handover.H_NORMAL
|
||||||
|
):
|
||||||
|
raise ParseError('全局库存无需正常交接')
|
||||||
|
|
||||||
|
is_global_rebatch = (
|
||||||
|
is_global_source
|
||||||
|
and attrs['type'] == Handover.H_NORMAL
|
||||||
|
and mtype in [Handover.H_DIV, Handover.H_MERGE]
|
||||||
|
)
|
||||||
|
if is_global_rebatch:
|
||||||
|
# 全局库存的拆批、合批不改变库存归属。
|
||||||
|
attrs['recive_mgroup'] = None
|
||||||
|
attrs['recive_dept'] = None
|
||||||
|
if new_wm and (
|
||||||
|
new_wm.mgroup_id is not None
|
||||||
|
or new_wm.belong_dept_id is not None
|
||||||
|
):
|
||||||
|
raise ParseError('全局库存合批目标必须是全局库存')
|
||||||
|
elif (
|
||||||
|
is_global_source
|
||||||
|
and attrs['type'] in [
|
||||||
|
Handover.H_REPAIR,
|
||||||
|
Handover.H_SCRAP,
|
||||||
|
Handover.H_CHANGE,
|
||||||
|
]
|
||||||
|
and not attrs.get('recive_mgroup')
|
||||||
|
):
|
||||||
|
raise ParseError('全局库存返修、报废或改版必须指定接收工段')
|
||||||
|
|
||||||
material_process = attrs['material'].process
|
material_process = attrs['material'].process
|
||||||
if (
|
if (
|
||||||
material_process
|
not is_global_rebatch
|
||||||
|
and material_process
|
||||||
and WmScope.requires_mgroup(material_process.into_wm_scope)
|
and WmScope.requires_mgroup(material_process.into_wm_scope)
|
||||||
and not attrs.get('recive_mgroup')
|
and not attrs.get('recive_mgroup')
|
||||||
):
|
):
|
||||||
raise ParseError('必须指定交接工段')
|
raise ParseError('必须指定交接工段')
|
||||||
if 'recive_mgroup' in attrs and attrs['recive_mgroup']:
|
if 'recive_mgroup' in attrs and attrs['recive_mgroup']:
|
||||||
attrs['recive_dept'] = attrs['recive_mgroup'].belong_dept
|
attrs['recive_dept'] = attrs['recive_mgroup'].belong_dept
|
||||||
if not attrs.get('recive_dept', None) and not attrs.get('recive_mgroup', None):
|
if (
|
||||||
|
not is_global_rebatch
|
||||||
|
and not attrs.get('recive_dept', None)
|
||||||
|
and not attrs.get('recive_mgroup', None)
|
||||||
|
):
|
||||||
raise ParseError('必须指定收料车间或收料工段')
|
raise ParseError('必须指定收料车间或收料工段')
|
||||||
if not attrs.get('send_dept', None) and not attrs.get('send_mgroup', None):
|
if (
|
||||||
|
not is_global_source
|
||||||
|
and not attrs.get('send_dept', None)
|
||||||
|
and not attrs.get('send_mgroup', None)
|
||||||
|
):
|
||||||
raise ParseError('必须指定送料车间或送料工段')
|
raise ParseError('必须指定送料车间或送料工段')
|
||||||
|
|
||||||
# if attrs["mtype"] == Handover.H_NORMAL and attrs.get("recive_mgroup", None) == attrs.get("send_mgroup", None):
|
# if attrs["mtype"] == Handover.H_NORMAL and attrs.get("recive_mgroup", None) == attrs.get("send_mgroup", None):
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,10 @@ from django.test import SimpleTestCase
|
||||||
|
|
||||||
from apps.mtm.models import Material, WmScope
|
from apps.mtm.models import Material, WmScope
|
||||||
from apps.wpm.filters import WMaterialFilter
|
from apps.wpm.filters import WMaterialFilter
|
||||||
from apps.wpm.models import WMaterial
|
from apps.wpm.models import Handover, WMaterial
|
||||||
from apps.wpm.serializers import WMaterialCreateSerializer
|
from apps.wpm.serializers import HandoverSerializer, WMaterialCreateSerializer
|
||||||
from apps.wpm.views import MlogbwViewSet
|
from apps.wpm.views import MlogbwViewSet
|
||||||
|
from rest_framework.exceptions import ParseError
|
||||||
|
|
||||||
|
|
||||||
class MlogbwViewSetTests(SimpleTestCase):
|
class MlogbwViewSetTests(SimpleTestCase):
|
||||||
|
|
@ -139,3 +140,73 @@ class WMaterialScopeTests(SimpleTestCase):
|
||||||
validated = WMaterialCreateSerializer().validate(attrs)
|
validated = WMaterialCreateSerializer().validate(attrs)
|
||||||
|
|
||||||
self.assertIs(validated["belong_dept"], dept)
|
self.assertIs(validated["belong_dept"], dept)
|
||||||
|
|
||||||
|
def test_global_inventory_cannot_enter_normal_handover(self):
|
||||||
|
wm = WMaterial(
|
||||||
|
material=Material(tracking=Material.MA_TRACKING_BATCH),
|
||||||
|
batch="GLOBAL-001",
|
||||||
|
count=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertRaisesMessage(ParseError, "全局库存无需正常交接"):
|
||||||
|
HandoverSerializer().validate({
|
||||||
|
"wm": wm,
|
||||||
|
"count": 1,
|
||||||
|
"type": Handover.H_NORMAL,
|
||||||
|
"mtype": Handover.H_NORMAL,
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_global_inventory_split_stays_global(self):
|
||||||
|
wm = WMaterial(
|
||||||
|
material=Material(tracking=Material.MA_TRACKING_BATCH),
|
||||||
|
batch="GLOBAL-001",
|
||||||
|
count=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
validated = HandoverSerializer().validate({
|
||||||
|
"wm": wm,
|
||||||
|
"count": 1,
|
||||||
|
"type": Handover.H_NORMAL,
|
||||||
|
"mtype": Handover.H_DIV,
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertIsNone(validated["send_dept"])
|
||||||
|
self.assertIsNone(validated["recive_dept"])
|
||||||
|
self.assertIsNone(validated["recive_mgroup"])
|
||||||
|
|
||||||
|
def test_global_inventory_cannot_merge_into_scoped_inventory(self):
|
||||||
|
material = Material(tracking=Material.MA_TRACKING_BATCH)
|
||||||
|
wm = WMaterial(material=material, batch="GLOBAL-001", count=1)
|
||||||
|
target = WMaterial(
|
||||||
|
material=material,
|
||||||
|
batch="GLOBAL-MERGED",
|
||||||
|
count=0,
|
||||||
|
belong_dept_id=20,
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertRaisesMessage(ParseError, "全局库存合批目标必须是全局库存"):
|
||||||
|
HandoverSerializer().validate({
|
||||||
|
"wm": wm,
|
||||||
|
"count": 1,
|
||||||
|
"new_wm": target,
|
||||||
|
"type": Handover.H_NORMAL,
|
||||||
|
"mtype": Handover.H_MERGE,
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_global_inventory_scrap_requires_receiving_mgroup(self):
|
||||||
|
wm = WMaterial(
|
||||||
|
material=Material(tracking=Material.MA_TRACKING_BATCH),
|
||||||
|
batch="GLOBAL-001",
|
||||||
|
count=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertRaisesMessage(
|
||||||
|
ParseError,
|
||||||
|
"全局库存返修、报废或改版必须指定接收工段",
|
||||||
|
):
|
||||||
|
HandoverSerializer().validate({
|
||||||
|
"wm": wm,
|
||||||
|
"count": 1,
|
||||||
|
"type": Handover.H_SCRAP,
|
||||||
|
"mtype": Handover.H_NORMAL,
|
||||||
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue