feat: 支持采购退货
This commit is contained in:
parent
2fbe1620fb
commit
0c7c1e4f17
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.2.12 on 2025-07-23 08:39
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inm', '0031_mioitem_unit_price'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mioitem',
|
||||||
|
name='note',
|
||||||
|
field=models.TextField(blank=True, null=True, verbose_name='备注'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mio',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(choices=[('do_out', '生产领料'), ('sale_out', '销售发货'), ('pur_in', '采购入库'), ('pur_out', '采购退货'), ('do_in', '生产入库'), ('other_in', '其他入库'), ('other_out', '其他出库')], default='do_out', help_text="(('do_out', '生产领料'), ('sale_out', '销售发货'), ('pur_in', '采购入库'), ('pur_out', '采购退货'), ('do_in', '生产入库'), ('other_in', '其他入库'), ('other_out', '其他出库'))", max_length=10, verbose_name='出入库类型'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -52,12 +52,13 @@ class MaterialBatchA(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
MIO_TYPE_PREFIX = {
|
MIO_TYPE_PREFIX = {
|
||||||
'do_out': 'SCLL', # 生产领料 (Shēngchǎn Lǐngliào)
|
'do_out': 'SCLL', # 生产领料
|
||||||
'sale_out': 'XSFH', # 销售发货 (Xiāoshòu Fāhuò)
|
'sale_out': 'XSFH', # 销售发货
|
||||||
'pur_in': 'CGRK', # 采购入库 (Cǎigòu Rùkù)
|
'pur_in': 'CGRK', # 采购入库
|
||||||
'do_in': 'SCRK', # 生产入库 (Shēngchǎn Rùkù)
|
'pur_out': 'CGTH', # 采购退货
|
||||||
'other_in': 'QTRK', # 其他入库 (Qítā Rùkù)
|
'do_in': 'SCRK', # 生产入库
|
||||||
'other_out': 'QTCK' # 其他出库 (Qítā Chūkù)
|
'other_in': 'QTRK', # 其他入库
|
||||||
|
'other_out': 'QTCK' # 其他出库
|
||||||
}
|
}
|
||||||
|
|
||||||
class MIO(CommonBDModel):
|
class MIO(CommonBDModel):
|
||||||
|
|
@ -67,6 +68,7 @@ class MIO(CommonBDModel):
|
||||||
MIO_TYPE_DO_OUT = 'do_out'
|
MIO_TYPE_DO_OUT = 'do_out'
|
||||||
MIO_TYPE_SALE_OUT = 'sale_out'
|
MIO_TYPE_SALE_OUT = 'sale_out'
|
||||||
MIO_TYPE_PUR_IN = 'pur_in'
|
MIO_TYPE_PUR_IN = 'pur_in'
|
||||||
|
MIO_TYPE_PUR_OUT = 'pur_out'
|
||||||
MIO_TYPE_DO_IN = 'do_in'
|
MIO_TYPE_DO_IN = 'do_in'
|
||||||
MIO_TYPE_OTHER_IN = 'other_in'
|
MIO_TYPE_OTHER_IN = 'other_in'
|
||||||
MIO_TYPE_OTHER_OUT = 'other_out'
|
MIO_TYPE_OTHER_OUT = 'other_out'
|
||||||
|
|
@ -75,6 +77,7 @@ class MIO(CommonBDModel):
|
||||||
(MIO_TYPE_DO_OUT, '生产领料'),
|
(MIO_TYPE_DO_OUT, '生产领料'),
|
||||||
(MIO_TYPE_SALE_OUT, '销售发货'),
|
(MIO_TYPE_SALE_OUT, '销售发货'),
|
||||||
(MIO_TYPE_PUR_IN, '采购入库'),
|
(MIO_TYPE_PUR_IN, '采购入库'),
|
||||||
|
(MIO_TYPE_PUR_OUT, '采购退货'),
|
||||||
(MIO_TYPE_DO_IN, '生产入库'),
|
(MIO_TYPE_DO_IN, '生产入库'),
|
||||||
(MIO_TYPE_OTHER_IN, '其他入库'),
|
(MIO_TYPE_OTHER_IN, '其他入库'),
|
||||||
(MIO_TYPE_OTHER_OUT, '其他出库')
|
(MIO_TYPE_OTHER_OUT, '其他出库')
|
||||||
|
|
@ -168,6 +171,7 @@ class MIOItem(BaseModel):
|
||||||
count_n_qt = models.PositiveIntegerField('其他', default=0)
|
count_n_qt = models.PositiveIntegerField('其他', default=0)
|
||||||
|
|
||||||
is_testok = models.BooleanField('检验是否合格', null=True, blank=True)
|
is_testok = models.BooleanField('检验是否合格', null=True, blank=True)
|
||||||
|
note = models.TextField('备注', null=True, blank=True)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def count_fields(cls):
|
def count_fields(cls):
|
||||||
|
|
|
||||||
|
|
@ -288,6 +288,13 @@ class InmService:
|
||||||
else:
|
else:
|
||||||
cls.update_mb(instance, 1)
|
cls.update_mb(instance, 1)
|
||||||
PumService.mio_purin(instance, is_reverse)
|
PumService.mio_purin(instance, is_reverse)
|
||||||
|
elif instance.type == MIO.MIO_TYPE_PUR_OUT:
|
||||||
|
from apps.pum.services import PumService
|
||||||
|
if is_reverse:
|
||||||
|
cls.update_mb(instance, 1)
|
||||||
|
else:
|
||||||
|
cls.update_mb(instance, -1)
|
||||||
|
PumService.mio_purout(instance, is_reverse)
|
||||||
elif instance.type == MIO.MIO_TYPE_OTHER_IN:
|
elif instance.type == MIO.MIO_TYPE_OTHER_IN:
|
||||||
if is_reverse:
|
if is_reverse:
|
||||||
BatchLog.clear(mio=instance)
|
BatchLog.clear(mio=instance)
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ class MIOViewSet(CustomModelViewSet):
|
||||||
if not has_perm(user, ['mio.sale']):
|
if not has_perm(user, ['mio.sale']):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
return MIOSaleSerializer
|
return MIOSaleSerializer
|
||||||
elif type == MIO.MIO_TYPE_PUR_IN:
|
elif type in [MIO.MIO_TYPE_PUR_IN, MIO.MIO_TYPE_PUR_OUT]:
|
||||||
if not has_perm(user, ['mio.pur']):
|
if not has_perm(user, ['mio.pur']):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
return MIOPurSerializer
|
return MIOPurSerializer
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ from rest_framework.exceptions import ValidationError
|
||||||
from apps.pum.models import PuOrderItem, PuPlan, PuPlanItem, PuOrder
|
from apps.pum.models import PuOrderItem, PuPlan, PuPlanItem, PuOrder
|
||||||
from django.db.models import F, Sum
|
from django.db.models import F, Sum
|
||||||
from apps.inm.models import MIO, MIOItem
|
from apps.inm.models import MIO, MIOItem
|
||||||
|
from rest_framework.exceptions import ParseError
|
||||||
|
|
||||||
|
|
||||||
class PumService:
|
class PumService:
|
||||||
|
|
@ -44,17 +45,33 @@ class PumService:
|
||||||
qs = MIOItem.objects.filter(mio=mio)
|
qs = MIOItem.objects.filter(mio=mio)
|
||||||
else:
|
else:
|
||||||
qs = MIOItem.objects.filter(id=mioitem.id)
|
qs = MIOItem.objects.filter(id=mioitem.id)
|
||||||
|
|
||||||
|
|
||||||
|
if mio.type == MIO.MIO_TYPE_PUR_IN:
|
||||||
|
if is_reverse:
|
||||||
|
xtype = "out"
|
||||||
|
else:
|
||||||
|
xtype = "in"
|
||||||
|
elif mio.type == MIO.MIO_TYPE_PUR_OUT:
|
||||||
|
if is_reverse:
|
||||||
|
xtype = "in"
|
||||||
|
else:
|
||||||
|
xtype = "out"
|
||||||
|
|
||||||
for i in qs:
|
for i in qs:
|
||||||
|
try:
|
||||||
pu_orderitem = PuOrderItem.objects.get(
|
pu_orderitem = PuOrderItem.objects.get(
|
||||||
material=i.material, pu_order=pu_order)
|
material=i.material, pu_order=pu_order)
|
||||||
if is_reverse:
|
except PuOrderItem.DoesNotExist:
|
||||||
|
raise ParseError(f'{str(i.material)}-采购订单中不存在该物料')
|
||||||
|
if xtype == "out":
|
||||||
delivered_count = pu_orderitem.delivered_count - i.count
|
delivered_count = pu_orderitem.delivered_count - i.count
|
||||||
else:
|
else:
|
||||||
delivered_count = pu_orderitem.delivered_count + i.count
|
delivered_count = pu_orderitem.delivered_count + i.count
|
||||||
if delivered_count > pu_orderitem.count:
|
if delivered_count > pu_orderitem.count:
|
||||||
raise ValidationError(f'{i.material.name}-超出采购订单所需数量')
|
raise ValidationError(f'{str(i.material)}-超出采购订单所需数量')
|
||||||
elif delivered_count < 0:
|
elif delivered_count < 0:
|
||||||
raise ValidationError(f'{i.material.name}-数量小于0')
|
raise ValidationError(f'{str(i.material)}-数量小于0')
|
||||||
pu_orderitem.delivered_count = delivered_count
|
pu_orderitem.delivered_count = delivered_count
|
||||||
pu_orderitem.save()
|
pu_orderitem.save()
|
||||||
pu_order_state = PuOrder.PUORDER_SHIP
|
pu_order_state = PuOrder.PUORDER_SHIP
|
||||||
|
|
@ -77,3 +94,4 @@ class PumService:
|
||||||
if len(states) == 1 and list(states)[0] == PuOrder.PUORDER_DONE:
|
if len(states) == 1 and list(states)[0] == PuOrder.PUORDER_DONE:
|
||||||
puplan.state = PuPlan.PUPLAN_DONE
|
puplan.state = PuPlan.PUPLAN_DONE
|
||||||
puplan.save()
|
puplan.save()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue