1
0
forked from erp-dev/erp
Files
erpnew/basic_info/models.py

386 lines
14 KiB
Python

from decimal import Decimal
from django.db import models
from flower.common import ModelBase
from django.contrib.auth.models import User
# ==================== 常量定义 ====================
METER_TO_YARD_RATE = 0.9144
YARD_TO_METER_RATE = 1.09361
# ==================== 枚举类定义 ====================
class WareHouseModeEnum(models.IntegerChoices):
"""仓库出入库模式枚举"""
RESTRICT_IN = 1, '严进宽出'
RESTRICT_IN_OUT = 2, '严进严出'
UNRESTRICTED = 3, '宽进宽出'
class MerchantTypeEnum(models.IntegerChoices):
"""商户类型枚举"""
STORE = 1, '布行'
FACTORY = 2, '印花厂'
class ProductUnitEnum(models.IntegerChoices):
"""产品单位枚举"""
METER = 1, ''
YARD = 2, ''
KG = 3, '公斤'
class EmployeeTypeEnum(models.TextChoices):
"""员工职位类型枚举"""
PRINTER = '打纸', '打纸'
ROLLING = '滚筒', '滚筒'
WARE = '仓库', '仓库'
DELIVERY = '送货', '送货'
class EmployeeStatusEnum(models.TextChoices):
"""员工状态枚举"""
ACTIVE = '在职', '在职'
INACTIVE = '离职', '离职'
class DeviceStatusEnum(models.TextChoices):
"""设备状态枚举"""
ACTIVE = '使用中', '使用中'
INACTIVE = '停用', '停用'
MAINTENANCE = '维修中', '维修中'
class DeviceTypeEnum(models.TextChoices):
"""设备类型枚举"""
ROLLING = '滚筒', '滚筒'
PRINTER = '打印', '打印'
# ==================== 模型定义 ====================
class QuickInput(ModelBase):
id = models.BigAutoField(primary_key=True)
name = models.CharField(max_length=100, verbose_name='')
value = models.CharField(max_length=200, verbose_name='')
group = models.CharField(verbose_name='')
def __str__(self):
return f'{self.group}-{self.name}'
class Meta:
verbose_name = '快捷输入'
verbose_name_plural = '快捷输入'
unique_together = ('name', 'group')
class Merchant(ModelBase):
id = models.BigAutoField(primary_key=True)
name = models.CharField(max_length=100, verbose_name='商户名称')
type = models.IntegerField(choices=MerchantTypeEnum.choices, verbose_name='商户类型')
area = models.CharField(max_length=100, blank=True, null=True, verbose_name='地区')
email = models.EmailField(blank=True, null=True, verbose_name='电子邮箱')
mobile = models.CharField(max_length=20, blank=True, null=True, verbose_name='手机')
contact = models.TextField(blank=True, null=True, verbose_name='联系人')
auto_complete_stock_change = models.BooleanField(
default=False,
verbose_name='自动确认库存变动',
)
description = models.TextField(blank=True, null=True, verbose_name='备注描述')
def __str__(self):
return self.name
class Meta:
verbose_name = '商户资料'
verbose_name_plural = '商户资料'
class VehicleType(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, related_name='vehicle_types', verbose_name='所属商户')
name = models.CharField(max_length=50, verbose_name='车辆类型名称')
description = models.TextField(blank=True, null=True, verbose_name='备注描述')
def __str__(self):
return self.name
class Meta:
verbose_name = '车辆类型'
verbose_name_plural = '车辆类型'
class WareHouse(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, related_name='warehouses', verbose_name='所属商户')
name = models.CharField(max_length=100, verbose_name='仓库名称')
location = models.CharField(max_length=200, blank=True, null=True, verbose_name='仓库地址')
mode = models.IntegerField(
choices=WareHouseModeEnum.choices,
default=WareHouseModeEnum.RESTRICT_IN,
verbose_name='出入库模式',
)
contact = models.CharField(max_length=100, blank=True, null=True, verbose_name='联系人')
mobile = models.CharField(max_length=20, blank=True, null=True, verbose_name='手机')
area = models.CharField(max_length=100, blank=True, null=True, verbose_name='地区')
description = models.TextField(blank=True, null=True, verbose_name='备注描述')
def __str__(self):
return self.name
class Meta:
verbose_name = '仓库资料'
verbose_name_plural = '仓库资料'
class Supplier(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, related_name='suppliers', verbose_name='所属商户')
name = models.CharField(max_length=100, verbose_name='供应商名称')
area = models.CharField(max_length=100, blank=True, null=True, verbose_name='地区')
email = models.EmailField(blank=True, null=True, verbose_name='电子邮箱')
mobile = models.CharField(max_length=20, blank=True, null=True, verbose_name='手机')
contact = models.TextField(blank=True, null=True, verbose_name='联系人')
description = models.TextField(blank=True, null=True, verbose_name='备注描述')
def __str__(self):
return self.name
class Meta:
verbose_name = '供应商'
verbose_name_plural = '供应商'
class BankAccount(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, related_name='bank_accounts', verbose_name='所属商户')
name = models.CharField(max_length=100, verbose_name='名称')
auto_number = models.CharField(max_length=50, verbose_name='自动编号')
description = models.TextField(blank=True, null=True, verbose_name='备注描述')
attachment = models.FileField(upload_to='bank_accounts/', blank=True, null=True, verbose_name='附件')
def __str__(self):
return f'{self.name} - {self.auto_number}'
class Meta:
verbose_name = '银行账户'
verbose_name_plural = '银行账户'
class ProductCategory(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, related_name='product_categories', verbose_name='所属商户')
name = models.CharField(max_length=100, verbose_name='类别名称')
description = models.TextField(blank=True, null=True, verbose_name='类别描述')
product_prefix = models.CharField(max_length=5, verbose_name='产品编号前缀')
def __str__(self):
return self.name
class Meta:
verbose_name = '产品类别'
verbose_name_plural = '产品类别'
class Product(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, verbose_name='所属商户')
category = models.ForeignKey(
ProductCategory,
on_delete=models.PROTECT,
related_name='products',
verbose_name='产品类别',
)
name = models.CharField(max_length=100, verbose_name='产品名')
human_id = models.CharField(max_length=100, verbose_name='产品编号', blank=True)
color = models.CharField(max_length=50, blank=True, null=True, verbose_name='颜色')
width_size = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, verbose_name='宽幅')
single_price_in = models.DecimalField(
max_digits=10,
decimal_places=2,
verbose_name='参考进价',
blank=True,
null=True,
)
single_price_out = models.DecimalField(
max_digits=10,
decimal_places=2,
verbose_name='参考售价',
blank=True,
null=True,
)
unit = models.IntegerField(
choices=ProductUnitEnum.choices,
default=ProductUnitEnum.METER,
verbose_name='单位',
)
spec = models.CharField(max_length=100, blank=True, null=True, verbose_name='规格')
description = models.TextField(blank=True, null=True, verbose_name='备注描述')
image = models.ImageField(
upload_to='product_images/',
blank=True,
null=True,
verbose_name='产品图片',
)
transform_rate = models.DecimalField(
max_digits=10,
decimal_places=4,
blank=True,
null=True,
verbose_name='公斤转换率',
)
def __str__(self):
return self.name
def save(
self,
*args,
force_insert=False,
force_update=False,
using=None,
update_fields=None,
):
super().save(
*args,
force_insert=force_insert,
force_update=force_update,
using=using,
update_fields=update_fields,
)
# Generate human_id if not set after saving to get the ID
if not self.human_id and self.category:
self.human_id = f'{self.category.product_prefix}{self.id:05d}'
super().save(
*args,
force_insert=False,
force_update=False,
using=using,
update_fields=['human_id'],
)
class Meta:
verbose_name = '产品资料'
verbose_name_plural = '产品资料'
class Customer(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, related_name='customers', verbose_name='所属商户')
name = models.CharField(max_length=100, verbose_name='客户名称')
visible_employees = models.ManyToManyField(
'Employee',
blank=True,
related_name='visible_customers',
verbose_name='可见该客户的员工',
)
created_by = models.ForeignKey(
'Employee',
on_delete=models.PROTECT,
related_name='created_customers',
null=True,
verbose_name='创建者',
)
mobile = models.CharField(max_length=20, verbose_name='手机')
area = models.CharField(max_length=100, blank=True, null=True, verbose_name='地区')
email = models.EmailField(blank=True, null=True, verbose_name='电子邮箱')
contact = models.CharField(blank=True, null=True, verbose_name='联系人')
description = models.TextField(blank=True, null=True, verbose_name='备注描述')
def __str__(self):
return self.name
class Meta:
verbose_name = '客户资料'
verbose_name_plural = '客户资料'
class Employee(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, related_name='employees', verbose_name='所属商户')
sys_user = models.OneToOneField(
User,
on_delete=models.PROTECT,
related_name='employee',
null=True,
blank=True,
verbose_name='系统用户',
)
name = models.CharField(max_length=100, verbose_name='员工姓名')
job_type = models.CharField(
max_length=20,
choices=EmployeeTypeEnum.choices,
default=EmployeeTypeEnum.PRINTER,
verbose_name='职位',
)
mobile = models.CharField(max_length=20, blank=True, null=True, verbose_name='手机')
area = models.CharField(max_length=100, blank=True, null=True, verbose_name='地区')
description = models.TextField(blank=True, null=True, verbose_name='备注描述')
status = models.CharField(
max_length=20,
choices=EmployeeStatusEnum.choices,
default=EmployeeStatusEnum.ACTIVE,
verbose_name='员工状态',
)
def __str__(self):
return self.name
class Meta:
verbose_name = '员工资料'
verbose_name_plural = '员工资料'
class DeviceInfo(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, related_name='devices', verbose_name='所属商户')
name = models.CharField(max_length=100, verbose_name='设备名称')
type = models.CharField(
max_length=20,
choices=DeviceTypeEnum.choices,
default=DeviceTypeEnum.ROLLING,
verbose_name='设备类型',
)
status = models.CharField(
max_length=20,
choices=DeviceStatusEnum.choices,
default=DeviceStatusEnum.ACTIVE,
verbose_name='设备状态',
)
start_working_at = models.DateField(blank=True, null=True, verbose_name='开始服役日期')
stop_working_at = models.DateField(blank=True, null=True, verbose_name='停止服役日期')
is_occupied = models.BooleanField(default=False, verbose_name='是否被占用')
description = models.TextField(blank=True, null=True, verbose_name='备注描述')
def __str__(self):
return self.name
class Meta:
verbose_name = '设备资料'
verbose_name_plural = '设备资料'
class VehicleTransportRecord(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, related_name='vehicle_transport_records', verbose_name='所属商户')
vehicle_type = models.ForeignKey(
VehicleType,
on_delete=models.PROTECT,
related_name='vehicles',
verbose_name='车次',
)
driver_name = models.CharField(max_length=100, verbose_name='司机姓名')
contact_number = models.CharField(max_length=20, blank=True, null=True, verbose_name='联系电话')
license_plate = models.CharField(max_length=20, verbose_name='车牌号码', null=True, blank=True)
delivery_date = models.DateField(verbose_name='送货日期')
def __str__(self):
return f'{self.vehicle_type}-{self.driver_name}-{self.delivery_date}'
class Meta:
verbose_name = '司机车次'
verbose_name_plural = '司机车次'