forked from erp-dev/erp
feat: transfer api for stock module
This commit is contained in:
131
stock/models.py
131
stock/models.py
@@ -371,3 +371,134 @@ class StockFreeze(ModelBase):
|
||||
class Meta:
|
||||
verbose_name = '库存冻结'
|
||||
verbose_name_plural = '库存冻结'
|
||||
|
||||
|
||||
class TransferOrderStatusEnum(models.IntegerChoices):
|
||||
DRAFT = 1, '待完成'
|
||||
COMPLETED = 2, '已完成'
|
||||
CANCELLED = 3, '已取消'
|
||||
|
||||
|
||||
class TransferOrder(ModelBase):
|
||||
"""跨仓调拨单"""
|
||||
|
||||
id = models.BigAutoField(primary_key=True)
|
||||
merchant = models.ForeignKey(
|
||||
basic_info_models.Merchant,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='transfer_orders',
|
||||
verbose_name='所属商户',
|
||||
)
|
||||
from_warehouse = models.ForeignKey(
|
||||
basic_info_models.WareHouse,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='outgoing_transfer_orders',
|
||||
verbose_name='调出仓',
|
||||
)
|
||||
to_warehouse = models.ForeignKey(
|
||||
basic_info_models.WareHouse,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='incoming_transfer_orders',
|
||||
verbose_name='调入仓',
|
||||
)
|
||||
mode = models.IntegerField(
|
||||
choices=basic_info_models.WareHouseModeEnum.choices,
|
||||
verbose_name='调拨模式',
|
||||
)
|
||||
operator = models.ForeignKey(
|
||||
basic_info_models.Employee,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='transfer_orders',
|
||||
verbose_name='经办人',
|
||||
)
|
||||
created_by = models.ForeignKey(
|
||||
'auth.User',
|
||||
on_delete=models.PROTECT,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name='created_transfer_orders',
|
||||
verbose_name='创建人',
|
||||
)
|
||||
transfer_date = models.DateField(verbose_name='调拨日期')
|
||||
status = models.IntegerField(
|
||||
choices=TransferOrderStatusEnum.choices,
|
||||
default=TransferOrderStatusEnum.DRAFT,
|
||||
verbose_name='状态',
|
||||
)
|
||||
remarks = models.TextField(blank=True, null=True, verbose_name='备注')
|
||||
request_id = models.CharField(max_length=64, blank=True, null=True, verbose_name='请求ID')
|
||||
outgoing_record = models.ForeignKey(
|
||||
'stock.StockChangeRecord',
|
||||
on_delete=models.PROTECT,
|
||||
related_name='transfer_out_orders',
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name='调出出入库记录',
|
||||
)
|
||||
incoming_record = models.ForeignKey(
|
||||
'stock.StockChangeRecord',
|
||||
on_delete=models.PROTECT,
|
||||
related_name='transfer_in_orders',
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name='调入出入库记录',
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '调拨单'
|
||||
verbose_name_plural = '调拨单'
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=['merchant', 'request_id'],
|
||||
condition=models.Q(request_id__isnull=False),
|
||||
name='unique_transfer_request_per_merchant',
|
||||
),
|
||||
models.CheckConstraint(
|
||||
check=~models.Q(from_warehouse=models.F('to_warehouse')),
|
||||
name='transfer_different_warehouses',
|
||||
),
|
||||
]
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
if self.from_warehouse_id and self.to_warehouse_id:
|
||||
if self.from_warehouse_id == self.to_warehouse_id:
|
||||
raise ValidationError('调拨的出入库仓库不能相同')
|
||||
if self.from_warehouse.merchant_id != self.merchant_id or self.to_warehouse.merchant_id != self.merchant_id:
|
||||
raise ValidationError('调拨仓库必须属于当前商户')
|
||||
if self.from_warehouse.mode != self.to_warehouse.mode:
|
||||
raise ValidationError('调拨要求出入库仓库的模式一致')
|
||||
if self.mode and self.mode != self.from_warehouse.mode:
|
||||
raise ValidationError('调拨模式与仓库模式不一致')
|
||||
|
||||
def __str__(self):
|
||||
return f'调拨单 {self.id} - {self.from_warehouse.name} -> {self.to_warehouse.name}'
|
||||
|
||||
|
||||
class TransferOrderItem(ModelBase):
|
||||
id = models.BigAutoField(primary_key=True)
|
||||
transfer_order = models.ForeignKey(
|
||||
TransferOrder,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='items',
|
||||
verbose_name='调拨单',
|
||||
)
|
||||
product = models.ForeignKey(
|
||||
basic_info_models.Product,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='transfer_order_items',
|
||||
verbose_name='产品',
|
||||
)
|
||||
unit = models.IntegerField(
|
||||
choices=basic_info_models.ProductUnitEnum.choices,
|
||||
verbose_name='单位',
|
||||
)
|
||||
total_quantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='数量合计')
|
||||
num_of_rolls = models.PositiveIntegerField(default=1, verbose_name='匹数')
|
||||
|
||||
class Meta:
|
||||
verbose_name = '调拨单明细'
|
||||
verbose_name_plural = '调拨单明细'
|
||||
|
||||
def __str__(self):
|
||||
return f'调拨明细 {self.id} - 产品: {self.product.name}'
|
||||
|
||||
Reference in New Issue
Block a user