183 lines
7.8 KiB
Python
183 lines
7.8 KiB
Python
from django.db import models
|
|
from apps.utils.models import BaseModel, CommonBDModel
|
|
from datetime import datetime
|
|
from django.db.models import Max, Sum
|
|
|
|
|
|
def _get_number(model_cls):
|
|
today_str = datetime.now().strftime('%Y%m%d')
|
|
prefix = model_cls.PREFIX
|
|
last_record = model_cls.objects.filter(
|
|
number__startswith=f"{prefix}-{today_str}"
|
|
).aggregate(Max('number'))['number__max']
|
|
if last_record:
|
|
last_number = int(last_record.split('-')[-1]) + 1
|
|
else:
|
|
last_number = 1
|
|
return f"{prefix}-{today_str}-{last_number:04d}"
|
|
|
|
|
|
class PurchaseRequisition(CommonBDModel):
|
|
"""
|
|
TN:物资申购单
|
|
"""
|
|
PREFIX = 'WZSG'
|
|
|
|
number = models.CharField('编号', max_length=20, unique=True)
|
|
phone = models.CharField('联系电话', max_length=20, null=True, blank=True)
|
|
req_date = models.DateField('申购日期', null=True, blank=True)
|
|
total_amount = models.DecimalField('合计金额', max_digits=14, decimal_places=2, default=0)
|
|
note = models.TextField('备注', null=True, blank=True)
|
|
ticket = models.OneToOneField(
|
|
'wf.ticket', verbose_name='关联工单',
|
|
on_delete=models.SET_NULL, null=True, blank=True,
|
|
related_name='mpr_ticket')
|
|
|
|
@classmethod
|
|
def get_a_number(cls):
|
|
return _get_number(cls)
|
|
|
|
|
|
class PurchaseRequisitionItem(BaseModel):
|
|
"""
|
|
TN:物资申购明细
|
|
"""
|
|
requisition = models.ForeignKey(
|
|
PurchaseRequisition, verbose_name='关联申购单',
|
|
on_delete=models.CASCADE, related_name='items')
|
|
item_name = models.CharField('物品名称', max_length=100)
|
|
spec = models.CharField('规格及型号', max_length=200, null=True, blank=True)
|
|
unit = models.CharField('单位', max_length=20, null=True, blank=True)
|
|
req_quantity = models.DecimalField('申购数量', max_digits=12, decimal_places=3, default=0)
|
|
current_stock = models.DecimalField('现库存量', max_digits=12, decimal_places=3, default=0)
|
|
need_date = models.DateField('需用日期', null=True, blank=True)
|
|
purchase_quantity = models.DecimalField('需采购数量', max_digits=12, decimal_places=3, default=0)
|
|
unit_price = models.DecimalField('单价', max_digits=14, decimal_places=2, default=0)
|
|
total_price = models.DecimalField('总价', max_digits=14, decimal_places=2, default=0)
|
|
note = models.TextField('备注', null=True, blank=True)
|
|
|
|
|
|
class WarehouseEntry(CommonBDModel):
|
|
"""
|
|
TN:仓库入库单
|
|
"""
|
|
PREFIX = 'CKRK'
|
|
|
|
ENTRY_TYPE_CHOICES = (
|
|
('raw_normal', '原材料正常入库'),
|
|
('raw_estimated', '原材料暂估入库'),
|
|
('product', '产品入库'),
|
|
('other', '其他'),
|
|
)
|
|
ENTRY_METHOD_CHOICES = (
|
|
('purchase', '采购'),
|
|
('self_made', '自制'),
|
|
('other', '其他'),
|
|
)
|
|
|
|
number = models.CharField('编号', max_length=20, unique=True)
|
|
warehouse = models.ForeignKey(
|
|
'inm.WareHouse', verbose_name='仓库',
|
|
on_delete=models.CASCADE, related_name='entries')
|
|
entry_date = models.DateField('入库日期', null=True, blank=True)
|
|
entry_type = models.CharField('入库类型', max_length=20, choices=ENTRY_TYPE_CHOICES, default='raw_normal')
|
|
entry_method = models.CharField('入库方式', max_length=20, choices=ENTRY_METHOD_CHOICES, default='purchase')
|
|
total_amount = models.DecimalField('合计金额', max_digits=14, decimal_places=2, default=0)
|
|
note = models.TextField('备注', null=True, blank=True)
|
|
ticket = models.OneToOneField(
|
|
'wf.ticket', verbose_name='关联工单',
|
|
on_delete=models.SET_NULL, null=True, blank=True,
|
|
related_name='warehouse_entry_ticket')
|
|
|
|
@classmethod
|
|
def get_a_number(cls):
|
|
return _get_number(cls)
|
|
|
|
|
|
class WarehouseEntryItem(BaseModel):
|
|
"""
|
|
TN:入库明细
|
|
"""
|
|
entry = models.ForeignKey(
|
|
WarehouseEntry, verbose_name='关联入库单',
|
|
on_delete=models.CASCADE, related_name='items')
|
|
name = models.CharField('名称', max_length=100)
|
|
spec = models.CharField('规格', max_length=200, null=True, blank=True)
|
|
unit = models.CharField('单位', max_length=20, null=True, blank=True)
|
|
quantity = models.DecimalField('数量', max_digits=12, decimal_places=3, default=0)
|
|
unit_price = models.DecimalField('单价', max_digits=14, decimal_places=2, default=0)
|
|
amount = models.DecimalField('金额', max_digits=14, decimal_places=2, default=0)
|
|
supplier_name = models.CharField('供应商名称', max_length=100, null=True, blank=True)
|
|
invoice_received = models.BooleanField('账单是否收到', default=False)
|
|
note = models.TextField('备注', null=True, blank=True)
|
|
|
|
|
|
class WarehouseStock(BaseModel):
|
|
"""
|
|
TN:物料库存(审批通过后入库)
|
|
"""
|
|
STATUS_CHOICES = (
|
|
('idle', '闲置'),
|
|
('in_requisition', '领用中'),
|
|
('requisitioned', '已领用'),
|
|
)
|
|
|
|
warehouse = models.ForeignKey(
|
|
'inm.WareHouse', verbose_name='仓库',
|
|
on_delete=models.CASCADE, related_name='mpr_stocks')
|
|
entry = models.ForeignKey(
|
|
WarehouseEntry, verbose_name='来源入库单',
|
|
on_delete=models.SET_NULL, null=True, blank=True, related_name='stocks')
|
|
entry_number = models.CharField('入库单号', max_length=20)
|
|
entry_date = models.DateField('入库日期', null=True, blank=True)
|
|
entry_type = models.CharField('入库类型', max_length=20, choices=WarehouseEntry.ENTRY_TYPE_CHOICES)
|
|
entry_method = models.CharField('入库方式', max_length=20, choices=WarehouseEntry.ENTRY_METHOD_CHOICES)
|
|
name = models.CharField('名称', max_length=100)
|
|
spec = models.CharField('规格', max_length=200, null=True, blank=True)
|
|
unit = models.CharField('单位', max_length=20, null=True, blank=True)
|
|
quantity = models.DecimalField('数量', max_digits=12, decimal_places=3, default=0)
|
|
unit_price = models.DecimalField('单价', max_digits=14, decimal_places=2, default=0)
|
|
amount = models.DecimalField('金额', max_digits=14, decimal_places=2, default=0)
|
|
supplier_name = models.CharField('供应商名称', max_length=100, null=True, blank=True)
|
|
invoice_received = models.BooleanField('账单是否收到', default=False)
|
|
status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES, default='idle')
|
|
|
|
|
|
class MaterialRequisition(CommonBDModel):
|
|
"""
|
|
TN:物资领用单
|
|
"""
|
|
PREFIX = 'WZLY'
|
|
|
|
number = models.CharField('编号', max_length=20, unique=True)
|
|
req_date = models.DateField('填报时间', null=True, blank=True)
|
|
collector = models.CharField('领取人', max_length=50, null=True, blank=True)
|
|
note = models.TextField('备注', null=True, blank=True)
|
|
ticket = models.OneToOneField(
|
|
'wf.ticket', verbose_name='关联工单',
|
|
on_delete=models.SET_NULL, null=True, blank=True,
|
|
related_name='material_requisition_ticket')
|
|
|
|
@classmethod
|
|
def get_a_number(cls):
|
|
return _get_number(cls)
|
|
|
|
|
|
class MaterialRequisitionItem(BaseModel):
|
|
"""
|
|
TN:物资领用明细
|
|
"""
|
|
requisition = models.ForeignKey(
|
|
MaterialRequisition, verbose_name='关联领用单',
|
|
on_delete=models.CASCADE, related_name='items')
|
|
is_stock_item = models.BooleanField('是否库存物品', default=True)
|
|
stock = models.ForeignKey(
|
|
WarehouseStock, verbose_name='关联库存',
|
|
on_delete=models.SET_NULL, null=True, blank=True, related_name='requisition_items')
|
|
req_type = models.CharField('领用类型', max_length=50, null=True, blank=True)
|
|
name = models.CharField('物资名称', max_length=100)
|
|
spec = models.CharField('规格型号', max_length=200, null=True, blank=True)
|
|
unit = models.CharField('单位', max_length=20, null=True, blank=True)
|
|
quantity = models.DecimalField('领用量', max_digits=12, decimal_places=3, default=0)
|
|
note = models.TextField('备注', null=True, blank=True)
|