forked from erp-dev/erp
feat: sales return order and purchase return order
This commit is contained in:
@@ -318,6 +318,224 @@ class SalesOrderItem(ModelBase):
|
||||
return round(self.price * self.real_quantity(), 2)
|
||||
|
||||
|
||||
class PurchaseReturnStatusEnum(models.IntegerChoices):
|
||||
PENDING = 1, '审批中'
|
||||
APPROVED = 2, '审批通过'
|
||||
CANCELLED = 3, '作废'
|
||||
|
||||
|
||||
class PurchaseReturnOrder(OrderItemsAggregationMixin, OrderDirectionMixin, OrderCounterpartyMixin, ModelBase):
|
||||
"""采购退货单(库存出库 + 供应商应付减少)"""
|
||||
|
||||
id = models.BigAutoField(primary_key=True)
|
||||
merchant = models.ForeignKey(
|
||||
basic_info_models.Merchant,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='purchase_return_orders',
|
||||
verbose_name='所属商户',
|
||||
)
|
||||
supplier = models.ForeignKey(
|
||||
basic_info_models.Supplier,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='purchase_return_orders',
|
||||
verbose_name='供应商',
|
||||
)
|
||||
purchase_order = models.ForeignKey(
|
||||
'PurchaseOrder',
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='return_orders',
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name='原采购单',
|
||||
)
|
||||
return_date = models.DateField(verbose_name='退货日期')
|
||||
operator = models.ForeignKey(
|
||||
basic_info_models.Employee,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='purchase_return_orders',
|
||||
verbose_name='经办人',
|
||||
)
|
||||
warehouse = models.ForeignKey(
|
||||
basic_info_models.WareHouse,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='purchase_return_orders',
|
||||
verbose_name='仓库',
|
||||
)
|
||||
status = models.IntegerField(
|
||||
choices=PurchaseReturnStatusEnum.choices,
|
||||
default=PurchaseReturnStatusEnum.PENDING,
|
||||
verbose_name='状态',
|
||||
)
|
||||
remarks = models.TextField(blank=True, null=True, verbose_name='备注')
|
||||
|
||||
class Meta:
|
||||
verbose_name = '采购退货单'
|
||||
verbose_name_plural = '采购退货单'
|
||||
|
||||
def __str__(self):
|
||||
return f'采购退货 {self.id} - {self.supplier.name}'
|
||||
|
||||
def get_direction(self) -> int:
|
||||
return -1
|
||||
|
||||
def get_counterparty_field_name(self) -> str:
|
||||
return 'supplier'
|
||||
|
||||
|
||||
class PurchaseReturnOrderItem(ModelBase):
|
||||
id = models.BigAutoField(primary_key=True)
|
||||
purchase_return_order = models.ForeignKey(
|
||||
PurchaseReturnOrder,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='items',
|
||||
verbose_name='采购退货单',
|
||||
)
|
||||
product = models.ForeignKey(
|
||||
basic_info_models.Product,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='purchase_return_order_items',
|
||||
verbose_name='产品',
|
||||
)
|
||||
price = models.DecimalField(max_digits=15, decimal_places=2, verbose_name='单价')
|
||||
color = models.CharField(max_length=50, null=True, blank=True, verbose_name='颜色')
|
||||
quantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='数量')
|
||||
unit = models.CharField(max_length=50, verbose_name='单位')
|
||||
spec = models.CharField(max_length=100, null=True, blank=True, verbose_name='规格')
|
||||
empty_diff_percent = models.DecimalField(max_digits=15, decimal_places=2, verbose_name='空差百分比')
|
||||
quantity_of_rolls = models.CharField(max_length=255, null=True, blank=True, verbose_name='各条数数量')
|
||||
num_of_rolls = models.PositiveIntegerField(default=1, verbose_name='条数')
|
||||
consume_detail_ids = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name='关联入库明细ID',
|
||||
)
|
||||
batch_number = models.CharField(null=True, blank=True, max_length=100, verbose_name='批次号')
|
||||
remarks = models.TextField(blank=True, null=True, verbose_name='备注')
|
||||
|
||||
class Meta:
|
||||
verbose_name = '采购退货明细'
|
||||
verbose_name_plural = '采购退货明细'
|
||||
|
||||
def real_quantity(self):
|
||||
return round(self.quantity * (1 - self.empty_diff_percent / 100), 2)
|
||||
|
||||
def diff_quantity(self):
|
||||
return round(self.quantity * (self.empty_diff_percent / 100), 2)
|
||||
|
||||
def total_amount(self):
|
||||
return round(self.price * self.real_quantity(), 2)
|
||||
|
||||
|
||||
class SalesReturnStatusEnum(models.IntegerChoices):
|
||||
PENDING = 1, '审批中'
|
||||
APPROVED = 2, '审批通过'
|
||||
CANCELLED = 3, '作废'
|
||||
|
||||
|
||||
class SalesReturnOrder(OrderItemsAggregationMixin, OrderDirectionMixin, OrderCounterpartyMixin, ModelBase):
|
||||
"""销售退货单(库存入库 + 客户应收减少)"""
|
||||
|
||||
id = models.BigAutoField(primary_key=True)
|
||||
merchant = models.ForeignKey(
|
||||
basic_info_models.Merchant,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='sales_return_orders',
|
||||
verbose_name='所属商户',
|
||||
)
|
||||
customer = models.ForeignKey(
|
||||
basic_info_models.Customer,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='sales_return_orders',
|
||||
verbose_name='客户',
|
||||
)
|
||||
sales_order = models.ForeignKey(
|
||||
'SalesOrder',
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='return_orders',
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name='原销售单',
|
||||
)
|
||||
return_date = models.DateField(verbose_name='退货日期')
|
||||
operator = models.ForeignKey(
|
||||
basic_info_models.Employee,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='sales_return_orders',
|
||||
verbose_name='经办人',
|
||||
)
|
||||
warehouse = models.ForeignKey(
|
||||
basic_info_models.WareHouse,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='sales_return_orders',
|
||||
verbose_name='仓库',
|
||||
)
|
||||
status = models.IntegerField(
|
||||
choices=SalesReturnStatusEnum.choices,
|
||||
default=SalesReturnStatusEnum.PENDING,
|
||||
verbose_name='状态',
|
||||
)
|
||||
remarks = models.TextField(blank=True, null=True, verbose_name='备注')
|
||||
|
||||
class Meta:
|
||||
verbose_name = '销售退货单'
|
||||
verbose_name_plural = '销售退货单'
|
||||
|
||||
def __str__(self):
|
||||
return f'销售退货 {self.id} - {self.customer.name}'
|
||||
|
||||
def get_direction(self) -> int:
|
||||
return 1
|
||||
|
||||
def get_counterparty_field_name(self) -> str:
|
||||
return 'customer'
|
||||
|
||||
|
||||
class SalesReturnOrderItem(ModelBase):
|
||||
id = models.BigAutoField(primary_key=True)
|
||||
sales_return_order = models.ForeignKey(
|
||||
SalesReturnOrder,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='items',
|
||||
verbose_name='销售退货单',
|
||||
)
|
||||
product = models.ForeignKey(
|
||||
basic_info_models.Product,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='sales_return_order_items',
|
||||
verbose_name='产品',
|
||||
)
|
||||
price = models.DecimalField(max_digits=15, decimal_places=2, verbose_name='单价')
|
||||
color = models.CharField(max_length=50, null=True, blank=True, verbose_name='颜色')
|
||||
quantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='数量')
|
||||
unit = models.CharField(max_length=50, verbose_name='单位')
|
||||
spec = models.CharField(max_length=100, null=True, blank=True, verbose_name='规格')
|
||||
empty_diff_percent = models.DecimalField(max_digits=15, decimal_places=2, verbose_name='空差百分比')
|
||||
quantity_of_rolls = models.CharField(max_length=255, null=True, blank=True, verbose_name='各条数数量')
|
||||
num_of_rolls = models.PositiveIntegerField(default=1, verbose_name='条数')
|
||||
consume_detail_ids = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name='关联入库明细ID',
|
||||
)
|
||||
batch_number = models.CharField(null=True, blank=True, max_length=100, verbose_name='批次号')
|
||||
remarks = models.TextField(blank=True, null=True, verbose_name='备注')
|
||||
|
||||
class Meta:
|
||||
verbose_name = '销售退货明细'
|
||||
verbose_name_plural = '销售退货明细'
|
||||
|
||||
def real_quantity(self):
|
||||
return round(self.quantity * (1 - self.empty_diff_percent / 100), 2)
|
||||
|
||||
def diff_quantity(self):
|
||||
return round(self.quantity * (self.empty_diff_percent / 100), 2)
|
||||
|
||||
def total_amount(self):
|
||||
return round(self.price * self.real_quantity(), 2)
|
||||
|
||||
|
||||
class PaymentOrderStatusEnum(models.IntegerChoices):
|
||||
PENDING = 1, '审批中'
|
||||
APPROVED = 2, '审批通过'
|
||||
@@ -474,6 +692,8 @@ class BalanceChangeSourceEnum(models.IntegerChoices):
|
||||
SALES_ORDER = 2, '销售单'
|
||||
PAYMENT_ORDER = 3, '付款单'
|
||||
RECEIPT_ORDER = 4, '收款单'
|
||||
PURCHASE_RETURN_ORDER = 5, '采购退货单'
|
||||
SALES_RETURN_ORDER = 6, '销售退货单'
|
||||
|
||||
|
||||
class BalanceChangeDirectionEnum(models.IntegerChoices):
|
||||
|
||||
Reference in New Issue
Block a user