feat(gerp): 员工档案字段重建 + 联系方式子表

EmployeeProfile 按新清单重建:删工号,新增姓名/性别/年龄/种族/政治面貌/生日、网络昵称/志愿/志愿工作、从事行业、设备与备注、派发设备与奖罚意愿、期望工作时段、躯体疾病/精神障碍、紧急联系人关系与自定义联系方式;员工名/部门名/职务改为关联只读展示(不再写 DeptName)。新增 EmployeeContact 子表与 0048 迁移;form_service 下发选项模板(性别/年龄/学历/行业/志愿/关系/疾病/设备)与 subform 列,add/modify 同步子表明细,get_table 注入职务与联系方式明细。
This commit is contained in:
TermiNexus committed 2026-10-01 19:36:45 +08:00
1 parent dc7f133b5f
commit 46be2bd3e2
3 files changed
+448 -15

No files matched your search

+61 -4
View File
@@ -9,21 +9,52 @@ from gvsds.model_base import QModel
class EmployeeProfile(QModel):
"""员工档案表——eHRM:员工基本信息与任职档案"""
"""员工档案表——eHRM:员工基本信息与任职档案
人员归属只认「部门员工关联」(UserRoleDepartmentUUID,表单虚拟列):
落库解析出 UserUUID / DeptUUID,员工名称与部门名称前端由关联解析展示(不在本表存名字)。
PositionName 是**只读联动**展示列(取该员工 UserRoleDepartmentPosition 的真实职务),不由表单填写。
"""
EmployeeProfileUUID = UUIDField(primary_key=True, verbose_name='档案UUID')
UserUUID = UUIDField(db_column='UserUUID', db_index=True, verbose_name='员工用户UUID')
TenantUUID = UUIDField(null=True, blank=True, db_column='TenantUUID', verbose_name='租户UUID')
CompanyUUID = UUIDField(db_column='CompanyUUID', verbose_name='公司UUID')
DeptUUID = UUIDField(null=True, blank=True, db_column='DeptUUID', verbose_name='部门UUID')
# DeptName 保留列(历史数据兼容):新档案不再写入,展示改用 DeptUUID 关联解析
DeptName = models.CharField(max_length=64, default='', verbose_name='部门名称')
EmployeeNo = models.CharField(max_length=32, default='', verbose_name='工号')
HireDate = models.DateField(null=True, blank=True, verbose_name='入职日期')
PositionName = models.CharField(max_length=64, default='', verbose_name='职务')
# ===== 基本信息 =====
EmployeeName = models.CharField(max_length=64, default='', verbose_name='姓名')
Gender = models.CharField(max_length=8, default='', verbose_name='性别')
AgeRange = models.CharField(max_length=16, default='', verbose_name='年龄')
Race = models.CharField(max_length=32, default='', verbose_name='种族')
PoliticalStatus = models.CharField(max_length=16, default='', verbose_name='政治面貌')
Education = models.CharField(max_length=32, default='', verbose_name='学历')
EmergencyContact = models.CharField(max_length=32, default='', verbose_name='紧急联系人')
EmergencyPhone = models.CharField(max_length=32, default='', verbose_name='紧急联系电话')
Address = models.CharField(max_length=256, default='', verbose_name='联系地址')
Birthday = models.DateField(null=True, blank=True, verbose_name='生日')
# ===== 网络与志愿 =====
Nickname = models.CharField(max_length=64, default='', verbose_name='网络常用昵称')
VolunteerWish = models.TextField(default='', verbose_name='志愿')
VolunteerWork = models.CharField(max_length=16, default='', verbose_name='志愿工作')
VolunteerWorkOther = models.CharField(max_length=64, default='', verbose_name='其它志愿工作')
Industry = models.CharField(max_length=32, default='', verbose_name='从事行业')
# ===== 工作条件 =====
Devices = models.CharField(max_length=256, default='', verbose_name='可参与工作的设备')
DeviceRemark = models.CharField(max_length=256, default='', verbose_name='设备备注')
AcceptDispatchDevice = models.BooleanField(default=False, verbose_name='是否愿意使用派发设备')
AcceptRewardPunish = models.BooleanField(default=False, verbose_name='是否接受奖罚机制')
ExpectedWorkHours = models.CharField(max_length=128, default='', verbose_name='期望工作时段')
# ===== 健康状况 =====
PhysicalIllness = models.CharField(max_length=512, default='', verbose_name='躯体疾病')
MentalIllness = models.CharField(max_length=512, default='', verbose_name='精神障碍')
# ===== 紧急联系人 =====
EmergencyContact = models.CharField(max_length=32, default='', verbose_name='紧急联系人姓名')
EmergencyRelation = models.CharField(max_length=16, default='', verbose_name='与本人关系')
EmergencyRelationOther = models.CharField(max_length=32, default='', verbose_name='其它关系说明')
EmergencyPhone = models.CharField(max_length=32, default='', verbose_name='紧急联系电话')
EmergencyContactCustom = models.CharField(max_length=128, default='', verbose_name='自定义联系方式')
Remark = models.CharField(max_length=512, default='', verbose_name='备注')
CreateTime = models.DateTimeField(default=datetime.datetime.utcnow, verbose_name='创建时间')
@@ -35,6 +66,32 @@ class EmployeeProfile(QModel):
verbose_name_plural = '员工档案'
class EmployeeContact(QModel):
"""员工联系方式子表——eHRM:一条 = 某份档案的一项联系方式
与 EmployeeProfile 一对多(每次保存档案时整体重写该档案的联系方式明细)。
ContactType 取值见 form_service.CONTACT_TYPE_OPTIONS(1=微信 2=QQ 3=邮箱
4=企业微信 5=X 6=个人网站 7=手机号)。
"""
EmployeeContactUUID = UUIDField(primary_key=True, verbose_name='联系方式UUID')
EmployeeProfileUUID = UUIDField(db_column='EmployeeProfileUUID', db_index=True, verbose_name='档案UUID')
UserUUID = UUIDField(null=True, blank=True, db_column='UserUUID', db_index=True, verbose_name='员工用户UUID')
TenantUUID = UUIDField(null=True, blank=True, db_column='TenantUUID', verbose_name='租户UUID')
CompanyUUID = UUIDField(db_column='CompanyUUID', verbose_name='公司UUID')
ContactType = models.SmallIntegerField(default=1, verbose_name='联系方式类型')
ContactValue = models.CharField(max_length=256, default='', verbose_name='联系方式')
ContactSort = models.IntegerField(default=0, verbose_name='排序')
CreateTime = models.DateTimeField(default=datetime.datetime.utcnow, verbose_name='创建时间')
class Meta:
db_table = 'EmployeeContact'
app_label = 'gerp'
ordering = ['ContactSort', 'CreateTime']
verbose_name = '员工联系方式'
verbose_name_plural = '员工联系方式'
class EmployeeAssessment(QModel):
"""员工考核表——eHRM:考核期间、评分与等级结论"""
+254 -11
View File
@@ -1,4 +1,5 @@
import uuid
import json
import datetime
import re
import logging
@@ -18,7 +19,7 @@ from gvsds.apps.gerp.models import (
App, AppPosition, AppVirtualPosition, AppVirtualBinding,
FinanceVoucher, FinanceVoucherEntry, FinanceCashier, FinanceLedger,
FinanceReport, FinanceReimburse, FinanceArap, FinanceBudget,
EmployeeProfile, EmployeeAssessment, EmployeePerformance,
EmployeeProfile, EmployeeContact, EmployeeAssessment, EmployeePerformance,
OaLeave, OaTravel, OaMeeting, OaAnnouncement, OaReport,
)
from gvsds.apps.core.models import User, UserAvatar, User2FA, UserPending2FA
@@ -167,7 +168,8 @@ DEPT_EMPLOYEE_PICKER_MULTI = {
#: eHRM 员工档案从「部门员工关联」解析后要落的列
#: (_ResolveDeptEmployee 返回值含 4 个键,各表只取自己表上存在的列,多带键会撞 model(**kwargs))
_PROFILE_DEPT_EMPLOYEE_KEYS = ('UserUUID', 'DeptUUID', 'DeptName')
#: DeptName 不在此列:部门名称不再写库(展示由 DeptUUID 关联解析),列仅保留给历史数据
_PROFILE_DEPT_EMPLOYEE_KEYS = ('UserUUID', 'DeptUUID')
class FormService(FormServiceBase):
@@ -224,6 +226,7 @@ class FormService(FormServiceBase):
'FinanceArap': FinanceArap,
'FinanceBudget': FinanceBudget,
'EmployeeProfile': EmployeeProfile,
'EmployeeContact': EmployeeContact,
'EmployeeAssessment': EmployeeAssessment,
'EmployeePerformance': EmployeePerformance,
'OaLeave': OaLeave,
@@ -527,6 +530,68 @@ class FormService(FormServiceBase):
],
}
# ==================== eHRM 员工档案(EmployeeProfile)选项模板 ====================
# 「模板」= 系统统一维护的选项常量(后端唯一下发,前端只渲染,禁止就地另写一份)
# 名称型选项统一**存中文文本**(列表直接可读,无需再映射);类型型(ContactType)存数字。
EMPLOYEE_PROFILE_SELECT_OPTIONS = {
'Gender': ['男', '女', '其他'],
'AgeRange': ['12~18', '19~25', '26~40', '41~65', '66以上'],
'PoliticalStatus': ['群众', '共青团员', '中共党员', '民主党派', '其他'],
'Education': ['小学', '初中', '高中', '中专', '大专', '本科', '硕士', '博士', '其他'],
'VolunteerWork': ['程序员', '画师', '测试者', '其它'],
'Industry': [
'IT/通信/电子/互联网',
'金融业',
'房地产/建筑业',
'商业服务',
'贸易/批发/零售/租赁业',
'文体教育/工艺美术',
'生产/加工/制造',
'交通/运输/物流/仓储',
'服务业',
'文化/传媒/娱乐/体育',
'能源/矿产/环保',
'政府/非盈利机构',
'学校',
],
'EmergencyRelation': ['父子', '母子', '配偶', '其它'],
}
#: 档案里的多选字段(tags 类型:选项固定 + 允许自定义,逗号分隔字符串存储)
EMPLOYEE_PROFILE_TAGS_OPTIONS = {
'Devices': ['电脑', '手机', '云服务器'],
'PhysicalIllness': [
'无', '先天发育畸形', '纹身', '内分泌、营养、代谢疾病', '泌尿生殖系统疾病',
'心血管疾病', '神经科疾病', '残疾', '消化系统疾病', '其他',
],
'MentalIllness': [
'无', '焦虑症', '抑郁症', '强迫症', '惊恐障碍', '单相情感障碍', '双相情感障碍', '其他',
],
}
#: 档案里用多行文本框的字段(长文本)
EMPLOYEE_PROFILE_TEXTAREA_FIELDS = ('VolunteerWish', 'Remark')
#: 档案表单里不需要用户选/填的字段:
#: 人员由「部门员工关联」一次选定,员工名/部门名/职务/部门名冗余列一律只读展示
EMPLOYEE_PROFILE_FORM_HIDDEN_FIELDS = (
'UserUUID', 'DeptUUID', 'DeptName', 'PositionName', 'TenantUUID', 'CompanyUUID',
)
#: 联系方式类型(EmployeeContact.ContactType):子表一行 = 一种渠道
CONTACT_TYPE_OPTIONS = [
{'value': 1, 'label': '微信'},
{'value': 2, 'label': 'QQ'},
{'value': 3, 'label': '邮箱'},
{'value': 4, 'label': '企业微信'},
{'value': 5, 'label': 'X'},
{'value': 6, 'label': '个人网站'},
{'value': 7, 'label': '手机号'},
]
#: 档案表单里「联系方式」子表的虚拟列名(值 = 明细行数组,随档案一并提交)
EMPLOYEE_CONTACT_FIELD = 'Contacts'
def get_columns(self, table_name):
model = self.TABLE_MAP.get(table_name)
if not model:
@@ -930,10 +995,63 @@ class FormService(FormServiceBase):
col['editable'] = False
col['hideInForm'] = True
col['visible'] = False
# EmployeeProfile 直接绑「部门-员工」关系:员工/部门/部门名由虚拟列
# UserRoleDepartmentUUID 一次选定,故三者在表单中隐藏(列表仍展示)
if table_name == 'EmployeeProfile' and pascal_name in ('UserUUID', 'DeptUUID', 'DeptName'):
col['hideInForm'] = True
# ===== eHRM 员工档案(EmployeeProfile):选项模板 + 只读联动列 =====
# 人员/部门由虚拟列「部门员工关联」一次选定;员工名/部门名/职务都是**只读联动**
# 展示(员工名与部门名来自关联 label,职务取该员工真实职务),一律不进表单。
if table_name == 'EmployeeProfile':
if pascal_name in self.EMPLOYEE_PROFILE_SELECT_OPTIONS:
col['type'] = 'select'
col['options'] = [
{'value': _v, 'label': _v}
for _v in self.EMPLOYEE_PROFILE_SELECT_OPTIONS[pascal_name]
]
col['placeholder'] = f"选择{col['title']}"
if pascal_name in self.EMPLOYEE_PROFILE_TAGS_OPTIONS:
# 多选:选项固定 + 允许自定义新增(满足「其它」),逗号分隔字符串存储
col['type'] = 'tags'
col['options'] = [
{'value': _v, 'label': _v}
for _v in self.EMPLOYEE_PROFILE_TAGS_OPTIONS[pascal_name]
]
col['tagsSeparator'] = ','
col['placeholder'] = f"选择{col['title']}(可多选,可自定义)"
if pascal_name in self.EMPLOYEE_PROFILE_TEXTAREA_FIELDS:
col['type'] = 'textarea'
if pascal_name in ('AcceptDispatchDevice', 'AcceptRewardPunish'):
col['type'] = 'switch'
col['defaultValue'] = False
if pascal_name in self.EMPLOYEE_PROFILE_FORM_HIDDEN_FIELDS:
col['editable'] = False
col['hideInForm'] = True
if pascal_name == 'DeptName':
# 部门名称不再由档案维护:展示改用 DeptUUID 关联解析(DeptUUID_label)
col['visible'] = False
if pascal_name == 'UserUUID':
col['title'] = '员工名称'
col['editable'] = False
if pascal_name == 'DeptUUID':
col['title'] = '部门名称'
col['editable'] = False
if pascal_name == 'PositionName':
# 职务只读联动:值由 get_table 从该员工 UserRoleDepartmentPosition 取真实职务
col['editable'] = False
# EmployeeContact(员工联系方式子表):只作为档案表单内嵌子表使用
# (列定义经 EmployeeProfile 的虚拟列 subform 下发,前端按此渲染增删行)
if table_name == 'EmployeeContact':
if pascal_name == 'ContactType':
col['title'] = '联系方式类型'
col['type'] = 'select'
col['options'] = [dict(_o) for _o in self.CONTACT_TYPE_OPTIONS]
col['required'] = True
col['placeholder'] = '选择类型'
elif pascal_name == 'ContactValue':
col['title'] = '联系方式'
col['required'] = True
col['placeholder'] = '如微信号 / 邮箱地址 / 手机号'
elif pascal_name == 'ContactSort':
col['type'] = 'number'
col['visible'] = False
col['hideInForm'] = True
if table_name == 'EmployeeAssessment' and pascal_name == 'UserUUID':
col['title'] = '员工'
if table_name == 'EmployeeAssessment' and pascal_name == 'AssessorUUID':
@@ -1119,11 +1237,16 @@ class FormService(FormServiceBase):
'visible': False, # 仅表单可见(列表已拆成"用户/角色"两列展示)
})
columns = virtual_cols + columns
# EmployeeProfile(员工档案)虚拟列"部门员工关联":直接选一条用户-角色-部门关系
# (UserRoleDepartment),选中即同时确定员工(UserUUID)与部门(DeptUUID/DeptName);
# 写库由 add_record / modify_record 解析该 UUID,列表仍展示真实列(员工/部门)。
# 选择器复用 DEPT_EMPLOYEE_PICKER(与工作组新增成员同一组件:按部门树分组浏览)
# EmployeeProfile(员工档案)两张虚拟列:
# 1) 「部门员工关联」(置顶):选一条 UserRoleDepartment,选中即确定员工与部门;
# 写库由 add_record / modify_record 解析该 UUID,列表仍展示真实列(员工/部门)
# 2) 「联系方式」子表单(置于表单末尾):明细行数组随档案一起提交,
# 保存后由 _RewriteEmployeeContacts 整体重写 EmployeeContact 子表
if table_name == 'EmployeeProfile':
_contact_fields = [
_c for _c in self.get_columns('EmployeeContact')
if _c.get('field') in ('ContactType', 'ContactValue', 'ContactSort')
]
columns = [{
'field': 'UserRoleDepartmentUUID',
'title': '部门员工关联',
@@ -1137,7 +1260,23 @@ class FormService(FormServiceBase):
# 新增缺省校验由后端在 add_record 内做(提示更精确)
'required': False,
'visible': False, # 仅表单可见:列表已有"员工/部门"真实列
}] + columns
}] + columns + [{
'field': self.EMPLOYEE_CONTACT_FIELD,
'title': '联系方式',
'titleEn': self.EMPLOYEE_CONTACT_FIELD,
'type': 'subform',
'subform': {
'table': 'EmployeeContact',
'title': '联系方式',
'addText': '添加联系方式',
'fields': _contact_fields,
},
'editable': True,
'sortable': False,
'filterable': False,
'required': False,
'visible': False, # 仅表单可见(列表不展示明细行)
}]
# 表单字段顺序:「部门员工关联」选择器置顶 —— 新增时先选它,员工/部门/角色随之确定,
# 其余字段(职务/类型等)都是派生或可选的
if table_name in self.DEPT_EMPLOYEE_FIRST_TABLES:
@@ -1555,6 +1694,23 @@ class FormService(FormServiceBase):
_prof_dept_names = _StrKeyMap(DepartmentManager.GetDepartmentNameMap(
[_urd.DeptUUID for _urd in _prof_pair.values() if _urd.DeptUUID]
))
# 职务只读联动:各档案对应「部门员工关联」的职务集合(UserRoleDepartmentPosition)
_prof_urd_ids = [
_pu for _pu in (
getattr(_u, 'UserRoleDepartmentUUID', None) for _u in _prof_pair.values()
) if _pu
]
_prof_pos_map = {}
if _prof_urd_ids:
_prof_pos_rows = PositionManager.GetUrdPositionRowsForUrds(_prof_urd_ids)
_prof_pos_names = _StrKeyMap(PositionManager.GetPositionNameMap(
{_p.PositionUUID for _p in _prof_pos_rows if _p.PositionUUID}
))
for _p in _prof_pos_rows:
_prod_key = _ProfStr(_p.UserRoleDepartmentUUID)
_prof_pos_map.setdefault(_prod_key, []).append(
_prof_pos_names.get(_ProfStr(_p.PositionUUID)) or _ProfStr(_p.PositionUUID)
)
for r in records:
_urd = _prof_pair.get((_ProfStr(r.get('UserUUID')), _ProfStr(r.get('DeptUUID'))))
if _urd is None:
@@ -1565,6 +1721,29 @@ class FormService(FormServiceBase):
r['UserRoleDepartmentUUID_label'] = (
f'{_dn} · {_un}' if (_dn or _un) else r['UserRoleDepartmentUUID']
)
_pl = _prof_pos_map.get(_ProfStr(_urd.UserRoleDepartmentUUID), [])
r['PositionName'] = '、'.join(_pl)
r['PositionName_label'] = r['PositionName']
# 联系方式子表明细(子表单回显):一次查出本页所有档案的明细行。
# 键统一用 UUIDObj 的字符串形式(模型读出来是 UUIDObj,记录字典里是字符串,
# 必须同一形态才能对上,见 _StrKeyMap 的同类说明)
_prof_uuids = [r.get('EmployeeProfileUUID') for r in records if r.get('EmployeeProfileUUID')]
if _prof_uuids:
_contact_map = {}
for _ct in EmployeeContact.objects.filter(
EmployeeProfileUUID__in=[_to_uuid_bytes(_x) for _x in _prof_uuids]):
_contact_map.setdefault(str(_ct.EmployeeProfileUUID), []).append({
'ContactType': _ct.ContactType,
'ContactValue': _ct.ContactValue,
'ContactSort': _ct.ContactSort,
})
for r in records:
_raw_pk = r.get('EmployeeProfileUUID')
_prof_key = str(UUIDObj(_to_uuid_bytes(_raw_pk))) if _raw_pk else ''
_rows = _contact_map.get(_prof_key, [])
r[self.EMPLOYEE_CONTACT_FIELD] = sorted(
_rows, key=lambda _x: _x.get('ContactSort') or 0
)
except Exception as e:
import logging
logging.error('[FormService] get_table error: table=%s, error=%s', table_name, e, exc_info=True)
@@ -1618,6 +1797,62 @@ class FormService(FormServiceBase):
'UserRoleUUID': user_role_bytes,
}, None
def _ParseContactsPayload(self, data):
"""解析档案表单提交的「联系方式」子表明细(虚拟列 Contacts)
一行 = {ContactType, ContactValue};空值行丢弃,行序即排序(ContactSort)。
Returns:
list[dict] | None: 未提交该字段返回 None(调用方据此保持原明细不动)
"""
raw = data.get(self.EMPLOYEE_CONTACT_FIELD)
if raw is None:
return None
if isinstance(raw, str):
try:
raw = json.loads(raw)
except Exception:
return []
if not isinstance(raw, (list, tuple)):
return []
rows = []
for _i, _item in enumerate(raw):
if not isinstance(_item, dict):
continue
_value = str(_item.get('ContactValue') or '').strip()
if not _value:
continue # 空行(用户加了行没填)直接丢弃
try:
_ctype = int(_item.get('ContactType') or 1)
except (TypeError, ValueError):
_ctype = 1
rows.append({'ContactType': _ctype, 'ContactValue': _value, 'ContactSort': _i})
return rows
def _RewriteEmployeeContacts(self, profile, rows):
"""按提交的明细整体重写某份档案的联系方式子表(rows=None 表示未提交,保持不动)"""
if rows is None:
return
profile_uuid = _to_uuid_bytes(getattr(profile, 'EmployeeProfileUUID', None))
if not profile_uuid:
return
try:
EmployeeContact.objects.filter(EmployeeProfileUUID=profile_uuid).delete()
except Exception:
logger.warning('[FormService] 清理员工联系方式失败: profile=%s', profile_uuid, exc_info=True)
return
for _row in rows:
EmployeeContact.objects.create(
EmployeeContactUUID=uuid.uuid4().bytes,
EmployeeProfileUUID=profile_uuid,
UserUUID=_to_uuid_bytes(getattr(profile, 'UserUUID', None)),
TenantUUID=_to_uuid_bytes(getattr(profile, 'TenantUUID', None)),
CompanyUUID=_to_uuid_bytes(getattr(profile, 'CompanyUUID', None)),
ContactType=_row['ContactType'],
ContactValue=_row['ContactValue'],
ContactSort=_row['ContactSort'],
)
def add_record(self, data):
table_name = data.get('Table', '')
model = self.TABLE_MAP.get(table_name)
@@ -2003,6 +2238,10 @@ class FormService(FormServiceBase):
CompanyUUID=getattr(_urd, 'CompanyUUID', None),
TenantUUID=getattr(_urd, 'TenantUUID', None),
)
# EmployeeProfile(员工档案):联系方式子表(虚拟列 Contacts)随档案一并提交,
# 主表没有该列 → 档案落库后按提交明细整体重写子表(未提交该字段则保持原明细)
if table_name == 'EmployeeProfile':
self._RewriteEmployeeContacts(obj, self._ParseContactsPayload(data))
# 审计日志:记录新增操作
self._record_audit(table_name, 'add', target_obj=obj, new_data=self._get_record_snapshot(obj))
# 工单创建:指派了处理人则通知对方(MsgType=2 工单通知)
@@ -2251,6 +2490,10 @@ class FormService(FormServiceBase):
self._send_workorder_notify(obj, _receiver, _wo_title, _wo_content)
if update_fields:
self._SaveObject(obj, update_fields)
# EmployeeProfile(员工档案):联系方式子表(虚拟列 Contacts)随档案一并提交,
# 主表没有该列 → 保存后按提交明细整体重写子表(未提交该字段则保持原明细)
if table_name == 'EmployeeProfile':
self._RewriteEmployeeContacts(obj, self._ParseContactsPayload(data))
# UserRole 表(员工列表)编辑"部门/职务":UserRole 自身无这两个字段(虚拟列),
# 提交时同步关系表 UserRoleDepartment(主关联:该 UserRole+公司首条)与职务子表
if table_name == 'UserRole' and ('DeptUUID' in data or 'PositionUUID' in data or 'PositionUUID_id' in data):
@@ -0,0 +1,133 @@
"""员工档案(EmployeeProfile)字段重建 + 新增联系方式子表(EmployeeContact)
删除 EmployeeNo(工号);新增姓名/性别/年龄/种族/政治面貌/生日、网络昵称/志愿/志愿工作、
从事行业、可参与工作的设备与备注、派发设备与奖罚机制意愿、期望工作时段、躯体疾病/精神障碍、
紧急联系人的关系与自定义联系方式;保留入职日期/职务(只读联动)/学历/地址/紧急联系人/备注。
新表 EmployeeContact 存档案的联系方式明细(档案 1:N)。
手写迁移:自动生成会夹带 communitycategory 等既有漂移,并触发交互式重命名询问。
"""
import datetime
from django.db import migrations, models
import gvsds.apps.core.models
class Migration(migrations.Migration):
dependencies = [
('gerp', '0047_app_pending_scope'),
]
operations = [
migrations.RemoveField(model_name='employeeprofile', name='EmployeeNo'),
migrations.AlterField(
model_name='employeeprofile', name='EmergencyContact',
field=models.CharField(default='', max_length=32, verbose_name='紧急联系人姓名'),
),
migrations.AddField(
model_name='employeeprofile', name='EmployeeName',
field=models.CharField(default='', max_length=64, verbose_name='姓名'),
),
migrations.AddField(
model_name='employeeprofile', name='Gender',
field=models.CharField(default='', max_length=8, verbose_name='性别'),
),
migrations.AddField(
model_name='employeeprofile', name='AgeRange',
field=models.CharField(default='', max_length=16, verbose_name='年龄'),
),
migrations.AddField(
model_name='employeeprofile', name='Race',
field=models.CharField(default='', max_length=32, verbose_name='种族'),
),
migrations.AddField(
model_name='employeeprofile', name='PoliticalStatus',
field=models.CharField(default='', max_length=16, verbose_name='政治面貌'),
),
migrations.AddField(
model_name='employeeprofile', name='Birthday',
field=models.DateField(blank=True, null=True, verbose_name='生日'),
),
migrations.AddField(
model_name='employeeprofile', name='Nickname',
field=models.CharField(default='', max_length=64, verbose_name='网络常用昵称'),
),
migrations.AddField(
model_name='employeeprofile', name='VolunteerWish',
field=models.TextField(default='', verbose_name='志愿'),
),
migrations.AddField(
model_name='employeeprofile', name='VolunteerWork',
field=models.CharField(default='', max_length=16, verbose_name='志愿工作'),
),
migrations.AddField(
model_name='employeeprofile', name='VolunteerWorkOther',
field=models.CharField(default='', max_length=64, verbose_name='其它志愿工作'),
),
migrations.AddField(
model_name='employeeprofile', name='Industry',
field=models.CharField(default='', max_length=32, verbose_name='从事行业'),
),
migrations.AddField(
model_name='employeeprofile', name='Devices',
field=models.CharField(default='', max_length=256, verbose_name='可参与工作的设备'),
),
migrations.AddField(
model_name='employeeprofile', name='DeviceRemark',
field=models.CharField(default='', max_length=256, verbose_name='设备备注'),
),
migrations.AddField(
model_name='employeeprofile', name='AcceptDispatchDevice',
field=models.BooleanField(default=False, verbose_name='是否愿意使用派发设备'),
),
migrations.AddField(
model_name='employeeprofile', name='AcceptRewardPunish',
field=models.BooleanField(default=False, verbose_name='是否接受奖罚机制'),
),
migrations.AddField(
model_name='employeeprofile', name='ExpectedWorkHours',
field=models.CharField(default='', max_length=128, verbose_name='期望工作时段'),
),
migrations.AddField(
model_name='employeeprofile', name='PhysicalIllness',
field=models.CharField(default='', max_length=512, verbose_name='躯体疾病'),
),
migrations.AddField(
model_name='employeeprofile', name='MentalIllness',
field=models.CharField(default='', max_length=512, verbose_name='精神障碍'),
),
migrations.AddField(
model_name='employeeprofile', name='EmergencyRelation',
field=models.CharField(default='', max_length=16, verbose_name='与本人关系'),
),
migrations.AddField(
model_name='employeeprofile', name='EmergencyRelationOther',
field=models.CharField(default='', max_length=32, verbose_name='其它关系说明'),
),
migrations.AddField(
model_name='employeeprofile', name='EmergencyContactCustom',
field=models.CharField(default='', max_length=128, verbose_name='自定义联系方式'),
),
migrations.CreateModel(
name='EmployeeContact',
fields=[
('EmployeeContactUUID', gvsds.apps.core.models.UUIDField(primary_key=True, serialize=False, verbose_name='联系方式UUID')),
('EmployeeProfileUUID', gvsds.apps.core.models.UUIDField(db_column='EmployeeProfileUUID', db_index=True, verbose_name='档案UUID')),
('UserUUID', gvsds.apps.core.models.UUIDField(blank=True, db_column='UserUUID', db_index=True, null=True, verbose_name='员工用户UUID')),
('TenantUUID', gvsds.apps.core.models.UUIDField(blank=True, db_column='TenantUUID', null=True, verbose_name='租户UUID')),
('CompanyUUID', gvsds.apps.core.models.UUIDField(db_column='CompanyUUID', verbose_name='公司UUID')),
('ContactType', models.SmallIntegerField(default=1, verbose_name='联系方式类型')),
('ContactValue', models.CharField(default='', max_length=256, verbose_name='联系方式')),
('ContactSort', models.IntegerField(default=0, verbose_name='排序')),
('CreateTime', models.DateTimeField(default=datetime.datetime.utcnow, verbose_name='创建时间')),
],
options={
'db_table': 'EmployeeContact',
'ordering': ['ContactSort', 'CreateTime'],
'verbose_name': '员工联系方式',
'verbose_name_plural': '员工联系方式',
},
),
]