Files
fzjg_local/fzjgact/huodong/models.py
2025-12-03 17:17:17 +08:00

328 lines
14 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.utils import timezone
class Branch(models.Model):
CATEGORY_CHOICES = (
('A型', 'A型'),
('B型', 'B型'),
('C型', 'C型'),
('不适用', '不适用'),
)
name = models.CharField(max_length=255, unique=True, verbose_name='分支机构名称')
location = models.CharField(max_length=255, verbose_name='所在省份')
contact_info = models.CharField(max_length=255, verbose_name='主要联系人')
description = models.TextField(blank=True, verbose_name='备注')
background_color = models.CharField(max_length=7, default='#EFF6FF', verbose_name='背景色',
help_text='使用#RRGGBB格式的颜色代码')
category = models.CharField(max_length=10, choices=CATEGORY_CHOICES, default='C型', verbose_name='分类')
is_mature = models.BooleanField(default=False, verbose_name='是否成熟')
def __str__(self):
return f'{self.name} 💼' if self.is_mature else self.name
class Meta:
verbose_name = '分支机构'
verbose_name_plural = '分支机构(基础信息)'
class Contact(models.Model):
branch = models.ForeignKey(Branch, on_delete=models.CASCADE, verbose_name='分支机构')
CATEGORY_CHOICES = [
('机房/设备间巡检人', '机房/设备间巡检人'),
('信息安全联系人', '信息安全联系人'),
('兼岗', '兼岗'),
('安全员', '安全员')
# 可以添加更多类别
]
# 修改为支持多选的 CharField
category = models.CharField(
max_length=255, # 增大长度原50可能不足
choices=CATEGORY_CHOICES,
verbose_name='联系人分类',
help_text='按住 Ctrl/Command 键多选(值将以逗号分隔存储)'
)
name = models.CharField(max_length=255, verbose_name='姓名')
phone = models.CharField(max_length=20, verbose_name='电话')
email = models.EmailField(blank=True, verbose_name='邮箱,可不填')
description = models.TextField(blank=True, verbose_name='描述,可不填')
def __str__(self):
return self.name
class Meta:
verbose_name = '联系人群'
verbose_name_plural = '联系人群'
class Activity(models.Model):
branch = models.ForeignKey(Branch, on_delete=models.CASCADE, verbose_name='分支机构')
name = models.CharField(max_length=255, verbose_name='活动名称')
scope = models.CharField(max_length=255, choices=(
('新建', '新建'),
('搬迁', '搬迁'),
('原址装修', '原址装修'),
('撤销', '撤销'),
('其他技术问题', '其他技术问题')
), verbose_name='活动类型')
start_time = models.DateField(verbose_name='开始日期')
end_time = models.DateField(blank=True, null=True, verbose_name='结束日期') # 可以为空,表示活动尚未结束
location = models.CharField(max_length=255, verbose_name='所在地点')
description = models.TextField(verbose_name='其它内容')
def __str__(self):
return self.name
class Meta:
verbose_name = '运营活动内容'
verbose_name_plural = '运营活动内容(新建搬迁装修和技术)'
class EquipmentImage(models.Model):
branch = models.ForeignKey(Branch, related_name='equipment_images', on_delete=models.CASCADE)
image = models.ImageField(upload_to='equipment_room_images/')
uploaded_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"设备间图片 {self.id} - {self.branch.name}"
class Meta:
verbose_name = '设备间图'
verbose_name_plural = '设备间图'
# 图纸的类
class Drawing(models.Model):
branch = models.ForeignKey(Branch, related_name='drawings', on_delete=models.CASCADE)
image = models.ImageField(upload_to='drawings/')
uploaded_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"图纸 {self.id} - {self.branch.name}"
class Meta:
verbose_name = '图纸'
verbose_name_plural = '图纸'
# 公共电子屏
class PublicScreen(models.Model):
SCREEN_TYPES = (
('marquee', '跑马灯'),
('advertisement', '广告屏'),
('information', '信息发布屏'),
)
branch = models.ForeignKey(Branch, on_delete=models.CASCADE, related_name='public_screens')
image = models.ImageField(upload_to='public_screen_images/', null=True, blank=True)
screen_type = models.CharField(max_length=20, choices=SCREEN_TYPES, verbose_name='功能类型', null=True, blank=True)
description = models.TextField(blank=True, null=True, verbose_name='功能描述')
last_drill = models.ForeignKey('Event', on_delete=models.SET_NULL, blank=True, null=True, related_name='public_screens', verbose_name='最后演练事件')
created_at = models.DateTimeField(default=timezone.now)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f'{self.branch.name} - {self.get_screen_type_display()} {self.id}'
class Meta:
verbose_name = '公共电子屏'
verbose_name_plural = '公共电子屏'
class Event(models.Model):
branches = models.ManyToManyField(Branch, related_name='events', verbose_name='分支机构')
name = models.CharField(max_length=255, verbose_name='事件名称')
start_time = models.DateField(verbose_name='开始时间')
end_time = models.DateField(blank=True, null=True, verbose_name='结束时间') # 可以为空,表示活动尚未结束
description = models.TextField(verbose_name='事件描述')
def __str__(self):
return self.name
class Meta:
verbose_name = '运营事件'
verbose_name_plural = '运营事件(其它)'
class VideoTerminal(models.Model):
TERMINAL_TYPES = (
('polycom', '宝利通终端'),
('zte', '中兴终端'),
('logitech', '罗技摄像头'),
('laptop_tv', '笔记本加电视'),
('laptop_projector', '笔记本加投影仪'),
('other', '其它'),
)
branch = models.ForeignKey(Branch, on_delete=models.CASCADE, related_name='video_terminals', verbose_name='分支机构')
terminal_type = models.CharField(max_length=20, choices=TERMINAL_TYPES, verbose_name='设备类型')
description = models.TextField(blank=True, verbose_name='设备描述')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
def __str__(self):
return f"{self.branch.name} - {self.get_terminal_type_display()}"
class Meta:
verbose_name = '视频设备终端'
verbose_name_plural = '视频设备终端'
class Evaluation(models.Model):
activity = models.ForeignKey(Activity, on_delete=models.CASCADE)
branch = models.ForeignKey(Branch, on_delete=models.CASCADE)
score = models.DecimalField(max_digits=4, decimal_places=2)
comment = models.TextField()
file_path = models.CharField(max_length=255, blank=True, null=True)
status = models.CharField(max_length=20,
choices=(('pending', '待审核'), ('approved', '已通过'), ('rejected', '已拒绝')),
default='pending')
def __str__(self):
return f"{self.activity.name} - {self.branch.name}"
# 预算相关模型
class Budget(models.Model):
"""预算主表"""
branch = models.ForeignKey(Branch, on_delete=models.CASCADE, verbose_name='分支机构')
name = models.CharField(max_length=255, verbose_name='预算名称')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
total_budget = models.DecimalField(max_digits=15, decimal_places=2, default=0, verbose_name='总预算')
def __str__(self):
return f"{self.branch.name} - {self.name} 预算"
class Meta:
verbose_name = '预算主表'
verbose_name_plural = '预算主表'
class EquipmentBudget(models.Model):
"""设备预算明细"""
BUDGET_TYPES = (
('本地询价采购', '本地询价采购'),
('订单采购', '订单采购'),
('按照总部配置要求本地询价采购', '按照总部配置要求本地询价采购'),
('本地询价采购或订单采购', '本地询价采购或订单采购')
)
budget = models.ForeignKey(Budget, related_name='equipment_budgets', on_delete=models.CASCADE, verbose_name='预算主表')
project = models.CharField(max_length=255, verbose_name='项目')
model = models.CharField(max_length=255, verbose_name='型号')
unit_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='单价')
procurement_method = models.CharField(max_length=50, choices=BUDGET_TYPES, verbose_name='采购方式')
quantity = models.IntegerField(default=1, verbose_name='数量')
subtotal = models.DecimalField(max_digits=12, decimal_places=2, default=0, verbose_name='小计')
def save(self, *args, **kwargs):
self.subtotal = self.unit_price * self.quantity
super().save(*args, **kwargs)
# 更新预算主表的总预算
self.update_total_budget()
def delete(self, *args, **kwargs):
super().delete(*args, **kwargs)
# 更新预算主表的总预算
self.update_total_budget()
def update_total_budget(self):
"""更新预算主表的总预算"""
total = self.budget.equipment_budgets.aggregate(total=models.Sum('subtotal'))['total'] or 0
total += self.budget.infrastructure_budgets.aggregate(total=models.Sum('subtotal'))['total'] or 0
self.budget.total_budget = total
self.budget.save()
def __str__(self):
return f"{self.project} - {self.model}"
class Meta:
verbose_name = '设备预算明细'
verbose_name_plural = '设备预算明细'
class InfrastructureBudget(models.Model):
"""基础设施预算明细"""
budget = models.ForeignKey(Budget, related_name='infrastructure_budgets', on_delete=models.CASCADE, verbose_name='预算主表')
name = models.CharField(max_length=255, verbose_name='名称')
remarks = models.TextField(blank=True, verbose_name='备注')
unit_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='单价')
unit = models.CharField(max_length=20, verbose_name='单位')
description = models.TextField(blank=True, verbose_name='说明')
quantity = models.IntegerField(default=1, verbose_name='数量')
subtotal = models.DecimalField(max_digits=12, decimal_places=2, default=0, verbose_name='小计')
def save(self, *args, **kwargs):
self.subtotal = self.unit_price * self.quantity
super().save(*args, **kwargs)
# 更新预算主表的总预算
self.update_total_budget()
def delete(self, *args, **kwargs):
super().delete(*args, **kwargs)
# 更新预算主表的总预算
self.update_total_budget()
def update_total_budget(self):
"""更新预算主表的总预算"""
total = self.budget.equipment_budgets.aggregate(total=models.Sum('subtotal'))['total'] or 0
total += self.budget.infrastructure_budgets.aggregate(total=models.Sum('subtotal'))['total'] or 0
self.budget.total_budget = total
self.budget.save()
def __str__(self):
return self.name
class Meta:
verbose_name = '基础设施预算明细'
verbose_name_plural = '基础设施预算明细'
class BudgetTemplate(models.Model):
"""预算模板"""
name = models.CharField(max_length=255, verbose_name='模板名称')
description = models.TextField(blank=True, verbose_name='模板描述')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
is_default = models.BooleanField(default=False, verbose_name='是否默认模板')
def __str__(self):
return self.name
class Meta:
verbose_name = '预算模板'
verbose_name_plural = '预算模板'
class TemplateEquipmentItem(models.Model):
"""模板设备项"""
template = models.ForeignKey(BudgetTemplate, related_name='equipment_items', on_delete=models.CASCADE, verbose_name='模板')
project = models.CharField(max_length=255, verbose_name='项目')
model = models.CharField(max_length=255, verbose_name='型号')
unit_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='参考单价')
procurement_method = models.CharField(max_length=50, choices=EquipmentBudget.BUDGET_TYPES, verbose_name='采购方式')
def __str__(self):
return f"{self.project} - {self.model}"
class Meta:
verbose_name = '模板设备项'
verbose_name_plural = '模板设备项'
class TemplateInfrastructureItem(models.Model):
"""模板基础设施项"""
template = models.ForeignKey(BudgetTemplate, related_name='infrastructure_items', on_delete=models.CASCADE, verbose_name='模板')
name = models.CharField(max_length=255, verbose_name='名称')
remarks = models.TextField(blank=True, verbose_name='备注')
unit_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='参考单价')
unit = models.CharField(max_length=20, verbose_name='单位')
description = models.TextField(blank=True, verbose_name='说明')
def __str__(self):
return self.name
class Meta:
verbose_name = '模板基础设施项'
verbose_name_plural = '模板基础设施项'