1
0
forked from erp-dev/erp
Files
erpnew/printing/models.py
2025-11-13 18:22:42 +08:00

331 lines
13 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from django.db import models
from django.conf import settings
from flower.common import ModelBase
from basic_info import models as basic_models
from stateflow import models as stateflow_models
class PlateOrder(ModelBase):
"""开版管理订单"""
# 自动编号相关
design_code = models.CharField(max_length=50, blank=True, null=True, verbose_name='设计编号')
# 版相关信息
plate_type = models.CharField(max_length=20, blank=True, null=True, verbose_name='起版情况') # 首版/复版等
plate_date = models.DateTimeField(null=True, blank=True, verbose_name='下版时间')
plate_method = models.CharField(max_length=50, blank=True, null=True, verbose_name='开版方式')
plate_image = models.FileField(upload_to='plate_images/', null=True, blank=True, verbose_name='开版图')
plate_notes = models.TextField(blank=True, null=True, verbose_name='打版注意事项')
reprint_reason = models.TextField(blank=True, null=True, verbose_name='复版原因')
# 状态和进程
# development_status = models.CharField(max_length=20, blank=True, null=True, verbose_name='开发进程') # 未打印/待画图等
urgency_level = models.CharField(max_length=20, default='正常', verbose_name='紧急程度') # 正常/加急
# 人员关联
salesperson = models.ForeignKey(
basic_models.Employee,
on_delete=models.PROTECT,
null=True,
blank=True,
related_name='plate_orders_as_salesperson',
verbose_name='销售员'
)
merchandiser = models.ForeignKey(
basic_models.Employee,
on_delete=models.PROTECT,
null=True,
blank=True,
related_name='plate_orders_as_merchandiser',
verbose_name='跟单员'
)
# 客户和地址信息
customer = models.ForeignKey(
basic_models.Customer,
on_delete=models.PROTECT,
related_name='plate_orders',
verbose_name='客户'
)
area = models.CharField(max_length=255, blank=True, null=True, verbose_name='区域')
default_address = models.CharField(max_length=500, blank=True, null=True, verbose_name='默认地址')
# 质量评级
is_mark_frame = models.BooleanField(default=False, verbose_name='是否套唛架')
drawing_rating = models.CharField(max_length=20, blank=True, null=True, verbose_name='画图评级')
color_matching_rating = models.CharField(max_length=20, blank=True, null=True, verbose_name='调色评级')
sample_rating = models.CharField(max_length=20, blank=True, null=True, verbose_name='套样评级')
difficulty_rating = models.CharField(max_length=20, blank=True, null=True, verbose_name='难度评级')
# 时间相关
required_completion_date = models.DateField(null=True, blank=True, verbose_name='要求完成时间')
completion_date = models.DateTimeField(null=True, blank=True, verbose_name='完成时间')
# 产品信息
fabric = models.CharField(max_length=100, blank=True, null=True, verbose_name='布料')
width = models.CharField(max_length=50, blank=True, null=True, verbose_name='幅宽')
style_name = models.CharField(max_length=100, blank=True, null=True, verbose_name='款号名称')
# 生产方式
production_method = models.CharField(max_length=50, blank=True, null=True, verbose_name='做货方式')
# 样品相关
sample_meter = models.CharField(max_length=100, blank=True, null=True, verbose_name='米样')
required_sample_meters = models.DecimalField(
max_digits=10,
decimal_places=2,
null=True,
blank=True,
verbose_name='客户要求米样米数'
)
# 审批和订单状态
approval_result = models.CharField(max_length=50, blank=True, null=True, verbose_name='审批结果')
is_ordered = models.BooleanField(default=False, verbose_name='是否已下单')
is_invalid = models.BooleanField(default=False, verbose_name='是否作废')
customer_feedback = models.TextField(blank=True, null=True, verbose_name='客户修改意见')
# 流程管理
business_object = models.OneToOneField(
stateflow_models.BusinessObject,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='plate_order',
verbose_name='流程实例',
)
def __str__(self):
return self.human_id or f'PlateOrder-{self.id}'
class Meta:
verbose_name = '开版订单'
verbose_name_plural = '开版订单'
ordering = ['-created_at']
permissions = [
('can_invalidate_plateorder', '可以作废开版订单'),
('can_activate_plateorder', '可以恢复开版订单'),
]
@property
def status(self) -> str:
"""返回当前状态名称"""
if not self.business_object:
return '未开始'
current_state = self.business_object.get_current_state()
# current_state 为 None 有两种情况:未开始或已完成
if current_state is None:
# 检查是否有完成记录来区分
has_completed_records = self.business_object.state_logs.filter(is_cancelled=False).exists()
if has_completed_records:
return '已完成'
else:
return '未开始'
return current_state.name
@property
def status_id(self):
"""返回当前状态ID"""
if not self.business_object:
return None
current_state = self.business_object.get_current_state()
return current_state.id if current_state else None
@property
def is_completed(self) -> bool:
"""判断是否完成"""
if not self.business_object:
return False
# 检查流程是否完成
from stateflow.services import get_overall_status
return get_overall_status(self.business_object) == 'completed'
@property
def has_started(self) -> bool:
"""判断是否已开始"""
if not self.business_object:
return False
# 检查是否有状态流转记录
from stateflow.models import StateFlowRecord
has_records = StateFlowRecord.objects.filter(
business_object=self.business_object
).exists()
return has_records
@property
def progress_percentage(self) -> float:
"""计算进度百分比"""
if not self.business_object:
return 0.0
return self.business_object.get_progress_percentage()
class PrintingOrder(ModelBase):
"""PrintingOrder model representing a printing order."""
customer = models.ForeignKey(
basic_models.Customer,
on_delete=models.PROTECT,
related_name='printing_orders',
verbose_name='客户',
)
fabric = models.CharField(max_length=100, verbose_name='面料')
width = models.CharField(max_length=100, verbose_name='幅宽')
is_urgent = models.BooleanField(default=False, verbose_name='紧急')
area = models.CharField(max_length=100, null=True, blank=True, verbose_name='地区')
address = models.CharField(max_length=200, null=True, blank=True, verbose_name='地址')
fabric_source = models.CharField(max_length=100, null=True, blank=True, verbose_name='布料来源')
is_fabric_received = models.BooleanField(default=False, verbose_name='布料是否已收')
craft = models.CharField(max_length=100, null=True, blank=True, verbose_name='工艺')
description = models.TextField(blank=True, null=True, verbose_name='订单描述')
outgoing_date = models.DateField(null=True, blank=True, verbose_name='出货日期')
curve = models.CharField(max_length=100, blank=True, null=True, verbose_name='曲线')
new_curve = models.CharField(max_length=100, blank=True, null=True, verbose_name='新加曲线')
position = models.TextField(blank=True, null=True, verbose_name='位置')
printing_warn = models.TextField(blank=True, null=True, verbose_name='打印注意事项')
rolling_warn = models.TextField(blank=True, null=True, verbose_name='滚筒注意事项')
production_warn = models.TextField(blank=True, null=True, verbose_name='生产注意事项')
is_invalid = models.BooleanField(default=False, verbose_name='是否作废')
process = models.ForeignKey(
stateflow_models.Process,
on_delete=models.PROTECT,
null=True,
blank=True,
related_name='printing_orders',
verbose_name='印染流程',
)
def __str__(self):
return self.human_id
class Meta:
verbose_name = '印染订单'
verbose_name_plural = '印染订单'
permissions = [
('can_invalidate_printingorder', '可以作废印染订单'),
('can_activate_printingorder', '可以恢复印染订单'),
]
@property
def human_id(self) -> str:
if self.id is None or self.created_at is None:
return ""
return f"{self.created_at.year}{self.created_at.month:02d}{self.created_at.day:02d}{self.id:06d}"
def can_change_process(self) -> bool:
"""检查是否可以修改流程所有job都未开始"""
return not any(job.has_started for job in self.printing_jobs.all())
@property
def progress(self) -> int:
"""计算订单完成进度百分比(已完成的任务数 / 总任务数)"""
jobs = self.printing_jobs.all()
if not jobs.exists():
return 0
completed_count = sum(1 for job in jobs if job.is_completed)
return int((completed_count / jobs.count()) * 100)
class PrintingJob(ModelBase):
"""PrintingJob model representing a printing job associated with an order."""
printing_order = models.ForeignKey(
PrintingOrder,
on_delete=models.CASCADE,
related_name='printing_jobs',
verbose_name='主订单',
)
product = models.ForeignKey(
basic_models.Product,
on_delete=models.PROTECT,
related_name='printing_jobs',
verbose_name='产品',
)
quantity = models.PositiveIntegerField(verbose_name='数量')
unit = models.CharField(max_length=50, verbose_name='单位')
size = models.CharField(max_length=100, null=True, blank=True, verbose_name='一段尺寸')
pieces = models.PositiveIntegerField(null=True, blank=True, verbose_name='件数')
description = models.TextField(blank=True, null=True, verbose_name='备注')
business_object = models.OneToOneField(
stateflow_models.BusinessObject,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='printing_job',
verbose_name='流程实例',
)
def __str__(self):
return self.printing_order.human_id
@property
def status(self) -> str:
"""返回当前状态名称"""
if not self.business_object:
return '未开始'
current_state = self.business_object.get_current_state()
# current_state 为 None 有两种情况:未开始或已完成
if current_state is None:
# 检查是否有完成记录来区分
has_completed_records = self.business_object.state_logs.filter(is_cancelled=False).exists()
if has_completed_records:
return '已完成'
else:
return '未开始'
return current_state.name
@property
def status_id(self):
"""返回当前状态ID"""
if not self.business_object:
return None
current_state = self.business_object.get_current_state()
return current_state.id if current_state else None
@property
def is_completed(self) -> bool:
"""判断是否完成(所有流程节点都已完成)"""
if not self.business_object or not self.printing_order.process:
return False
# 获取流程的所有节点
process_nodes = self.printing_order.process.process_nodes.all()
total_nodes = process_nodes.count()
if total_nodes == 0:
return False
# 检查已完成的节点数
completed_count = self.business_object.state_logs.filter(is_cancelled=False).count()
# 所有节点都完成了才算完成
return completed_count >= total_nodes
@property
def has_started(self) -> bool:
"""判断是否已开始有BusinessObject且有状态记录或不在初始状态"""
if not self.business_object:
return False
# 检查是否有状态流转记录
from stateflow.models import StateFlowRecord
has_records = StateFlowRecord.objects.filter(
business_object=self.business_object
).exists()
return has_records
class Meta:
verbose_name = '印染款式明细'
verbose_name_plural = '印染款式明细'