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)