feat: 新增hrm --人员交接表

This commit is contained in:
TianyangZhang 2025-12-22 13:41:38 +08:00
parent dec8650af1
commit b250b9b078
5 changed files with 162 additions and 9 deletions

View File

@ -0,0 +1,57 @@
# Generated by Django 3.2.12 on 2025-12-22 05:40
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('system', '0006_auto_20241213_1249'),
('wf', '0006_auto_20251215_1645'),
('hrm', '0022_empneed'),
]
operations = [
migrations.CreateModel(
name='EmpPersonInfo',
fields=[
('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('name', models.CharField(max_length=20, verbose_name='姓名')),
('gender', models.CharField(default='', max_length=10, verbose_name='性别')),
('IDcard', models.CharField(max_length=20, verbose_name='身份证号')),
('phone', models.CharField(blank=True, max_length=20, null=True, validators=[django.core.validators.RegexValidator('^1[3456789]\\d{9}$', '手机号码格式不正确')], verbose_name='手机号')),
('note', models.TextField(blank=True, null=True, verbose_name='备注')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='emppersoninfo_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='emppersoninfo_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='EmpJoin',
fields=[
('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('person', models.JSONField(default=list, verbose_name='人员信息')),
('join_date', models.DateField(verbose_name='入职日期')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='empjoin_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('dept_need', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='system.dept', verbose_name='入职部门')),
('ticket', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='empjoin_ticket', to='wf.ticket', verbose_name='关联工单')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='empjoin_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
],
options={
'abstract': False,
},
),
]

View File

@ -4,8 +4,9 @@ from apps.system.models import Post, User
from apps.utils.models import BaseModel, CommonADModel, CommonAModel, CommonBModel
from django.utils import timezone
from datetime import timedelta
from django.core.validators import RegexValidator
PHONE_VALIDATOR = RegexValidator(r'^1[3456789]\d{9}$', '手机号码格式不正确')
class Employee(CommonBModel):
"""
TN:员工信息
@ -220,4 +221,27 @@ class EmpNeed(CommonADModel):
education = models.CharField('学历要求', max_length=50, help_text='高中/大专/不限')
professional_requirement = models.TextField(verbose_name="相关专业及技能要求", null=True, blank=True)
ticket = models.OneToOneField('wf.ticket', verbose_name='关联工单',
on_delete=models.CASCADE, related_name='empneed_ticket', null=True, blank=True)
on_delete=models.CASCADE, related_name='empneed_ticket', null=True, blank=True)
class EmpJoin(CommonADModel):
"""
TN:员工入职
"""
dept_need = models.ForeignKey('system.Dept', verbose_name='入职部门', on_delete=models.CASCADE)
ticket = models.OneToOneField('wf.ticket', verbose_name='关联工单',
on_delete=models.CASCADE, related_name='empjoin_ticket', null=True, blank=True)
person = models.JSONField('人员信息', default=list)
join_date = models.DateField('入职日期')
class EmpPersonInfo(CommonADModel):
"""
TN:入职人员信息
"""
name = models.CharField('姓名', max_length=20)
gender = models.CharField('性别', max_length=10, default='')
IDcard = models.CharField('身份证号', max_length=20)
phone = models.CharField('手机号', max_length=20,validators=[PHONE_VALIDATOR], null=True, blank=True)
note = models.TextField('备注', null=True, blank=True)

View File

@ -9,7 +9,7 @@ from django.utils import timezone
from apps.utils.serializers import CustomModelSerializer
from apps.utils.constants import EXCLUDE_FIELDS
from apps.hrm.models import (Certificate, ClockRecord, Employee,
NotWorkRemark, Attendance, Resignation, EmpNeed)
NotWorkRemark, Attendance, Resignation, EmpNeed, EmpJoin, EmpPersonInfo)
from apps.system.serializers import DeptSimpleSerializer, UserSimpleSerializer
from django.db import transaction
from django.core.cache import cache
@ -347,4 +347,59 @@ class EmpNeedSerializer(CustomModelSerializer):
ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
class Meta:
model = EmpNeed
fields = '__all__'
fields = '__all__'
class EmpJoinSerializer(CustomModelSerializer):
ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
class Meta:
model = EmpJoin
fields = '__all__'
class EmpPersonInfoSerializer(CustomModelSerializer):
class Meta:
model = EmpPersonInfo
fields = (
'name',
'gender',
'IDcard',
'phone',
'note',
)
class EmpJoinApproveSerializer(CustomModelSerializer):
empjoin_id = serializers.IntegerField()
def validate_empjoin_id(self, value):
try:
empjoin = EmpJoin.objects.get(id=value)
except EmpJoin.DoesNotExist:
raise ParseError('该入职申请不存在')
if not isinstance(empjoin.person, list) or not empjoin.person:
raise ParseError('该入职申请未添加人员')
self.empjoin = empjoin
return value
def validate(self, attrs):
"""
校验 person 中每一个人员
"""
self.person_serializers = []
errors = []
for index, item in enumerate(self.empjoin.person):
serializer = EmpPersonInfoSerializer(data=item)
if serializer.is_valid():
self.person_serializers.append(serializer)
else:
errors.append({
"index": index,
"errors": serializer.errors
})
if errors:
raise serializers.ValidationError({"person": errors})
return attrs
@transaction.atomic
def create(self, validated_data):
objs = [EmpPersonInfo(**serializer.validated_data) for serializer in self.person_serializers]
EmpPersonInfo.objects.bulk_create(objs)
return objs

View File

@ -1,5 +1,5 @@
from apps.hrm.views import (CertificateViewSet, ClockRecordViewSet, EmployeeViewSet, NotWorkRemarkViewSet, EmpNeedViewSet,
AttendanceViewSet, ResignationViewSet)
AttendanceViewSet, ResignationViewSet, EmpJoinViewSet)
from django.urls import path, include
from rest_framework.routers import DefaultRouter
@ -15,6 +15,7 @@ router.register('certificate', CertificateViewSet, basename='certificate')
router.register('attendance', AttendanceViewSet, basename='attendance')
router.register('resignation', ResignationViewSet, basename='resignation')
router.register('empneed', EmpNeedViewSet, basename='empneed')
router.register('empjoin', EmpJoinViewSet, basename='empjoin')
urlpatterns = [
path(API_BASE_URL, include(router.urls)),
]

View File

@ -12,15 +12,15 @@ from rest_framework.response import Response
from apps.hrm.errors import NO_NEED_LEVEL_REMARK
from apps.hrm.filters import (CertificateFilterSet, ClockRecordFilterSet, EmployeeFilterSet,
NotWorkRemarkFilterSet)
from apps.hrm.models import Certificate, ClockRecord, Employee, NotWorkRemark, Attendance, Resignation, EmpNeed
from apps.hrm.serializers import (CertificateCreateUpdateSerializer, CertificateSerializer, ChannelAuthoritySerializer,
from apps.hrm.models import Certificate, ClockRecord, Employee, NotWorkRemark, Attendance, Resignation, EmpNeed, EmpJoin
from apps.hrm.serializers import (CertificateCreateUpdateSerializer, CertificateSerializer, ChannelAuthoritySerializer, EmpJoinSerializer,
ClockRecordListSerializer,
EmployeeCreateUpdateSerializer, EmployeeDetailSerializer, EmployeeImproveSerializer,
EmployeeNotWorkRemarkSerializer,
EmployeeSerializer,
ClockRecordSimpleSerializer, ClockRecordCreateSerializer,
NotWorkRemarkListSerializer, CorrectSerializer, AttendanceSerializer,
ResignationSerializer, EmpNeedSerializer)
ResignationSerializer, EmpNeedSerializer, EmpJoinApproveSerializer)
from apps.hrm.services import HrmService
from apps.third.dahua import dhClient
@ -430,4 +430,20 @@ class EmpNeedViewSet(TicketMixin, EuModelViewSet):
workflow_key = "wf_empneed"
def gen_other_ticket_data(self, instance):
return {"post_need": instance.post_need}
return {"post_need": instance.post_need}
class EmpJoinViewSet(TicketMixin, EuModelViewSet):
queryset = EmpJoin.objects.all()
serializer_class = EmpJoinSerializer
workflow_key = "wf_empjoin"
@action(methods=['post'], detail=True)
def approve(self, request, pk=None):
serializer = EmpJoinApproveSerializer(data={'empjoin_id': pk})
serializer.is_valid(raise_exception=True)
person = serializer.save()
return Response({
"msg":"审批通过,人员入库",
"count": len(person)
})