feat: 支持采购退货

This commit is contained in:
caoqianming 2025-07-24 10:50:11 +08:00
parent 2fbe1620fb
commit 0c7c1e4f17
5 changed files with 64 additions and 12 deletions

View File

@ -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='出入库类型'),
),
]

View File

@ -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):

View File

@ -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)

View File

@ -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

View File

@ -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)
for i in qs:
pu_orderitem = PuOrderItem.objects.get(
material=i.material, pu_order=pu_order) if mio.type == MIO.MIO_TYPE_PUR_IN:
if is_reverse: 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:
try:
pu_orderitem = PuOrderItem.objects.get(
material=i.material, pu_order=pu_order)
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()