factory/apps/sam/models.py

222 lines
8.5 KiB
Python

from decimal import Decimal
from django.db import models
from django.db.models import Sum
from apps.utils.models import CommonBModel, BaseModel, CommonBDModel
from apps.mtm.models import Material
# Create your models here.
class Customer(CommonBModel):
"""
TN:客户信息
"""
name = models.CharField('客户名称', max_length=50, unique=True)
address = models.CharField('详细地址', max_length=20, blank=True, null=True)
contact = models.CharField('联系人', max_length=20)
contact_phone = models.CharField(
'联系电话', max_length=11, unique=True, null=True)
description = models.CharField('描述', max_length=200, blank=True, null=True)
class Meta:
verbose_name = '客户信息'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class Contract(CommonBDModel):
"""
TN:合同信息
"""
STATUS_DRAFT = 10
STATUS_ACTIVE = 20
STATUS_DONE = 30
STATUS_TERMINATED = 40
STATUS_CHOICES = (
(STATUS_DRAFT, '草稿'),
(STATUS_ACTIVE, '执行中'),
(STATUS_DONE, '已完成'),
(STATUS_TERMINATED, '已终止'),
)
SETTLEMENT_UNRECEIVED = 10
SETTLEMENT_PARTIAL = 20
SETTLEMENT_FULL = 30
SETTLEMENT_CHOICES = (
(SETTLEMENT_UNRECEIVED, '未到款'),
(SETTLEMENT_PARTIAL, '部分到款'),
(SETTLEMENT_FULL, '全部到款'),
)
name = models.CharField('合同名称', max_length=100)
number = models.CharField('合同编号', max_length=100, unique=True)
amount = models.IntegerField('合同金额', default=0)
customer = models.ForeignKey(Customer, verbose_name='关联客户',
on_delete=models.CASCADE, related_name='contract_customer')
sign_date = models.DateField('签订日期')
effective_date = models.DateField('生效日期', null=True, blank=True)
end_date = models.DateField('截止日期', null=True, blank=True)
status = models.PositiveSmallIntegerField(
'合同状态', choices=STATUS_CHOICES, default=STATUS_DRAFT, help_text=str(STATUS_CHOICES))
settlement_status = models.PositiveSmallIntegerField(
'结算状态', choices=SETTLEMENT_CHOICES, default=SETTLEMENT_UNRECEIVED, help_text=str(SETTLEMENT_CHOICES))
received_amount = models.DecimalField('累计已到款', max_digits=14, decimal_places=2, default=0)
unreceived_amount = models.DecimalField('累计未到款', max_digits=14, decimal_places=2, default=0)
receive_progress = models.DecimalField('到款进度', max_digits=5, decimal_places=2, default=0)
description = models.CharField('描述', max_length=200, blank=True, null=True)
class Meta:
verbose_name = '合同信息'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
def save(self, *args, **kwargs):
refresh_settlement = kwargs.pop('refresh_settlement', True)
super().save(*args, **kwargs)
if refresh_settlement:
self.refresh_settlement()
def refresh_settlement(self):
received_amount = ContractRecord.objects.filter(contract=self).aggregate(
total=Sum('amount')
)['total'] or Decimal('0.00')
contract_amount = Decimal(str(self.amount or 0)).quantize(Decimal('0.01'))
unreceived_amount = contract_amount - received_amount
if unreceived_amount < Decimal('0.00'):
unreceived_amount = Decimal('0.00')
if contract_amount <= Decimal('0.00'):
receive_progress = Decimal('0.00')
else:
receive_progress = (received_amount * Decimal('100.00') / contract_amount).quantize(Decimal('0.01'))
if receive_progress > Decimal('100.00'):
receive_progress = Decimal('100.00')
if received_amount <= Decimal('0.00'):
settlement_status = self.SETTLEMENT_UNRECEIVED
elif received_amount >= contract_amount and contract_amount > Decimal('0.00'):
settlement_status = self.SETTLEMENT_FULL
else:
settlement_status = self.SETTLEMENT_PARTIAL
status = self.status
if status != self.STATUS_TERMINATED:
if received_amount <= Decimal('0.00'):
status = self.STATUS_DRAFT
elif received_amount >= contract_amount and contract_amount > Decimal('0.00'):
status = self.STATUS_DONE
else:
status = self.STATUS_ACTIVE
type(self).objects.filter(pk=self.pk).update(
received_amount=received_amount,
unreceived_amount=unreceived_amount,
receive_progress=receive_progress,
settlement_status=settlement_status,
status=status,
)
self.received_amount = received_amount
self.unreceived_amount = unreceived_amount
self.receive_progress = receive_progress
self.settlement_status = settlement_status
self.status = status
class Order(CommonBModel):
"""
TN:订单信息
"""
ORDER_CREATE = 10
ORDER_SUBMITED = 20
ORDER_DOING = 30
ORDER_DELIVERED = 40
ORDER_STATES = (
(10, '创建中'),
(20, '已提交'),
(30, '进行中'),
(40, '已交付')
)
state = models.PositiveSmallIntegerField(
'订单状态', default=ORDER_CREATE, choices=ORDER_STATES, help_text=str(ORDER_STATES))
number = models.CharField('订单编号', max_length=100, unique=True)
customer = models.ForeignKey(
Customer, verbose_name='客户', on_delete=models.CASCADE)
contract = models.ForeignKey(
Contract, verbose_name='所属合同', null=True, blank=True, on_delete=models.SET_NULL)
delivery_date = models.DateField('截止交货日期')
items = models.ManyToManyField(
Material, verbose_name='订单明细', through='sam.orderitem', blank=True)
submit_time = models.DateTimeField('提交时间', null=True, blank=True)
class Meta:
verbose_name = '订单信息'
verbose_name_plural = verbose_name
class OrderItem(BaseModel):
"""
TN:订单明细
"""
order = models.ForeignKey(
Order, verbose_name='关联订单', on_delete=models.CASCADE, related_name='item_order')
material = models.ForeignKey(
Material, verbose_name='所需产品', on_delete=models.CASCADE, related_name='orderitem_material')
count = models.PositiveIntegerField('所需数量', default=1)
delivered_count = models.PositiveIntegerField('已交货数量', default=0)
utask = models.ForeignKey('pm.utask', verbose_name='关联生产大任务',
on_delete=models.SET_NULL, null=True, blank=True)
class ContractRecord(CommonBDModel):
"""
TN:销售合同到款流水
"""
STAGE_FIRST = 10
STAGE_MIDDLE = 20
STAGE_FINAL = 30
STAGE_OTHER = 40
STAGE_CHOICES = (
(STAGE_FIRST, '首款'),
(STAGE_MIDDLE, '中间款'),
(STAGE_FINAL, '尾款'),
(STAGE_OTHER, '其他'),
)
PAY_BANK = 10
PAY_CASH = 20
PAY_ACCEPTANCE = 30
PAY_WECHAT = 40
PAY_ALIPAY = 50
PAY_OTHER = 60
PAY_METHOD_CHOICES = (
(PAY_BANK, '银行转账'),
(PAY_CASH, '现金'),
(PAY_ACCEPTANCE, '承兑'),
(PAY_WECHAT, '微信'),
(PAY_ALIPAY, '支付宝'),
(PAY_OTHER, '其他'),
)
contract = models.ForeignKey(
Contract, verbose_name='销售合同', on_delete=models.CASCADE, related_name='records')
record_date = models.DateField('到款日期')
amount = models.DecimalField('到款金额', max_digits=14, decimal_places=2)
stage_type = models.PositiveSmallIntegerField(
'阶段类型', choices=STAGE_CHOICES, default=STAGE_OTHER, help_text=str(STAGE_CHOICES))
pay_method = models.PositiveSmallIntegerField(
'收款方式', choices=PAY_METHOD_CHOICES, default=PAY_BANK, help_text=str(PAY_METHOD_CHOICES))
voucher_no = models.CharField('凭证号', max_length=100, null=True, blank=True)
remark = models.CharField('备注', max_length=200, null=True, blank=True)
class Meta:
verbose_name = '销售合同到款流水'
verbose_name_plural = verbose_name
ordering = ['-record_date', '-create_time']
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.contract.refresh_settlement()
def delete(self, using=None, *args, **kwargs):
contract = self.contract
result = super().delete(using=using, *args, **kwargs)
contract.refresh_settlement()
return result