feat: wpm中增加到岗记录

This commit is contained in:
caoqianming 2023-11-20 16:26:14 +08:00
parent cbce572350
commit fddadfe30c
8 changed files with 134 additions and 18 deletions

View File

@ -57,6 +57,7 @@ class PmService:
""" """
从大任务自动排产出小任务 从大任务自动排产出小任务
""" """
from apps.wpm.services import make_sflogs
if utask.state != Utask.UTASK_CREATED: if utask.state != Utask.UTASK_CREATED:
raise ParseError('任务状态异常') raise ParseError('任务状态异常')
utask.state = Utask.UTASK_DECOMPOSE utask.state = Utask.UTASK_DECOMPOSE
@ -82,6 +83,8 @@ class PmService:
'update_by': user, 'update_by': user,
'is_count_utask': True 'is_count_utask': True
}) })
make_sflogs(mgroup=utask.mgroup,
start_date=task_date, end_date=task_date, create_by=user)
else: else:
# 获取产品的加工路线 # 获取产品的加工路线
rqs = Route.get_routes(product) rqs = Route.get_routes(product)
@ -131,6 +134,8 @@ class PmService:
'update_by': user, 'update_by': user,
'is_count_utask': val.is_count_utask 'is_count_utask': val.is_count_utask
}) })
make_sflogs(mgroup=mgroup,
start_date=task_date, end_date=task_date, create_by=user)
@classmethod @classmethod
def check_orderitems(cls, orderitems: QuerySet[OrderItem]): def check_orderitems(cls, orderitems: QuerySet[OrderItem]):

View File

@ -0,0 +1,42 @@
# Generated by Django 3.2.12 on 2023-11-20 08:23
from django.conf import settings
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', '0002_myschedule'),
('wpm', '0031_alter_mlog_mtask'),
]
operations = [
migrations.AddField(
model_name='sflog',
name='work_date',
field=models.DateField(blank=True, null=True, verbose_name='值班日期'),
),
migrations.CreateModel(
name='AttLog',
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='删除标记')),
('state', models.CharField(choices=[('pending', '待定'), ('normal', '正常'), ('late', '迟到'), ('early_leave', '早退'), ('absent', '未到岗'), ('leave', '请假')], default='pending', help_text="[('pending', '待定'), ('normal', '正常'), ('late', '迟到'), ('early_leave', '早退'), ('absent', '未到岗'), ('leave', '请假')]", max_length=20, verbose_name='状态')),
('note', models.TextField(blank=True, default='', verbose_name='备注信息')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='attlog_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='system.post', verbose_name='岗位')),
('sflog', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.sflog', verbose_name='关联值班记录')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='attlog_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='到岗人')),
],
options={
'abstract': False,
},
),
]

View File

@ -32,6 +32,7 @@ class SfLog(CommonADModel):
Shift, verbose_name='当班班次', on_delete=models.CASCADE) Shift, verbose_name='当班班次', on_delete=models.CASCADE)
leader = models.ForeignKey( leader = models.ForeignKey(
'system.user', verbose_name='班长', on_delete=models.CASCADE, null=True, blank=True) 'system.user', verbose_name='班长', on_delete=models.CASCADE, null=True, blank=True)
work_date = models.DateField('值班日期', null=True, blank=True)
start_time = models.DateTimeField('值班开始') start_time = models.DateTimeField('值班开始')
end_time = models.DateTimeField('值班结束') end_time = models.DateTimeField('值班结束')
note = models.TextField('其他备注', null=True, blank=True) note = models.TextField('其他备注', null=True, blank=True)
@ -179,3 +180,27 @@ class Handover(CommonADModel):
submit_time = models.DateTimeField('提交时间', null=True, blank=True) submit_time = models.DateTimeField('提交时间', null=True, blank=True)
submit_user = models.ForeignKey( submit_user = models.ForeignKey(
User, verbose_name='提交人', on_delete=models.CASCADE, null=True, blank=True, related_name='handover_submit_user') User, verbose_name='提交人', on_delete=models.CASCADE, null=True, blank=True, related_name='handover_submit_user')
class AttLog(CommonADModel):
"""
到岗记录
"""
ATT_STATE_CHOICES = [
('pending', '待定'),
('normal', '正常'),
('late', '迟到'),
('early_leave', '早退'),
('absent', '未到岗'),
('leave', '请假'),
# 可以根据需要添加更多状态
]
sflog = models.ForeignKey(
SfLog, verbose_name='关联值班记录', on_delete=models.CASCADE)
user = models.ForeignKey(
'system.user', verbose_name='到岗人', on_delete=models.CASCADE)
post = models.ForeignKey(
'system.post', verbose_name='岗位', on_delete=models.CASCADE)
state = models.CharField('状态', max_length=20,
choices=ATT_STATE_CHOICES, default='pending', help_text=str(ATT_STATE_CHOICES))
note = models.TextField('备注信息', default='', blank=True)

View File

@ -3,13 +3,15 @@ from apps.utils.serializers import CustomModelSerializer
from rest_framework import serializers from rest_framework import serializers
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from .models import SfLog, StLog, SfLogExp, WMaterial, Mlog, Handover, Mlogb from .models import SfLog, StLog, SfLogExp, WMaterial, Mlog, Handover, Mlogb, AttLog
from apps.system.models import Dept, User from apps.system.models import Dept, User
from apps.system.serializers import UserSimpleSerializer from apps.system.serializers import UserSimpleSerializer
from apps.pm.models import Mtask from apps.pm.models import Mtask
from apps.wpm.tasks import cal_enstat_when_pcoal_heat_change, cal_enstat_when_team_change from apps.wpm.tasks import cal_enstat_when_pcoal_heat_change, cal_enstat_when_team_change
from apps.mtm.models import Mgroup, TeamMember, Shift
from apps.mtm.serializers import MaterialSimpleSerializer from apps.mtm.serializers import MaterialSimpleSerializer
from django.db import transaction from django.db import transaction
from django.utils import timezone
class StLogSerializer(CustomModelSerializer): class StLogSerializer(CustomModelSerializer):
@ -37,16 +39,26 @@ class SfLogSerializer(CustomModelSerializer):
} }
def update(self, instance, validated_data): def update(self, instance, validated_data):
old_pcoal_heat = instance.pcoal_heat with transaction.atomic():
old_team = instance.team old_pcoal_heat = instance.pcoal_heat
instance = super().update(instance, validated_data) old_team = instance.team
new_pcoal_heat = instance.pcoal_heat instance: SfLog = super().update(instance, validated_data)
new_team = instance.team new_pcoal_heat = instance.pcoal_heat
if new_pcoal_heat != old_pcoal_heat: new_team = instance.team
cal_enstat_when_pcoal_heat_change.delay(instance.id) mgroup: Mgroup = instance.mgroup
if new_team != old_team: if new_pcoal_heat != old_pcoal_heat and mgroup.need_enm:
cal_enstat_when_team_change.delay(instance.id) cal_enstat_when_pcoal_heat_change.delay(instance.id)
return instance if new_team != old_team:
default_state = 'pending'
if timezone.now() > instance.end_time:
default_state = 'normal'
# 分配班组时创建人员到岗情况
for item in TeamMember.objects.filter(team=new_team, mgroup=instance.mgroup):
AttLog.objects.get_or_create(sflog=instance, user=item.user, defaults={
'sflog': instance, 'user': item.user, 'post': item.post, 'state': default_state, 'create_by': self.context['request'].user})
if mgroup.need_enm:
cal_enstat_when_team_change.delay(instance.id)
return instance
# def to_internal_value(self, data): # def to_internal_value(self, data):
# if hasattr(self.Meta, 'update_fields') and self.context['request'].method in ['PUT', 'PATCH']: # if hasattr(self.Meta, 'update_fields') and self.context['request'].method in ['PUT', 'PATCH']:
# u_fields = self.Meta.update_fields # u_fields = self.Meta.update_fields
@ -111,6 +123,8 @@ class MlogSerializer(CustomModelSerializer):
source='equipment.name', read_only=True) source='equipment.name', read_only=True)
equipment_2_name = serializers.CharField( equipment_2_name = serializers.CharField(
source='equipment_2.name', read_only=True) source='equipment_2.name', read_only=True)
shift = serializers.PrimaryKeyRelatedField(
label='班次ID', queryset=Shift.objects.all(), required=True)
shift_name = serializers.CharField(source='shift.name', read_only=True) shift_name = serializers.CharField(source='shift.name', read_only=True)
mlogb = MlogbSerializer( mlogb = MlogbSerializer(
label='多产出件信息', many=True, required=False) label='多产出件信息', many=True, required=False)
@ -251,3 +265,16 @@ class MlogAnaSerializer(serializers.Serializer):
start_date = serializers.DateField(label='开始日期', required=True) start_date = serializers.DateField(label='开始日期', required=True)
end_date = serializers.DateField(label='结束日期', required=True) end_date = serializers.DateField(label='结束日期', required=True)
material_cate = serializers.CharField(label='物料系列', required=False) material_cate = serializers.CharField(label='物料系列', required=False)
class AttLogSerializer(CustomModelSerializer):
mgroup_name = serializers.CharField(
source='sflog.mgroup.name', read_only=True)
user_name = serializers.CharField(source='user.name', read_only=True)
post_name = serializers.CharField(source='post.name', read_only=True)
belong_dept_name = serializers.CharField(
source='sflog.mgroup.belong_dept.name', read_only=True)
class Meta:
model = AttLog
fields = '__all__'

View File

@ -16,8 +16,10 @@ from apps.mtm.models import Mgroup, Shift, Material, Route
from .models import SfLog, SfLogExp, WMaterial, Mlog, Mlogb, Handover from .models import SfLog, SfLogExp, WMaterial, Mlog, Mlogb, Handover
def make_sflogs(mgroup: Mgroup, start_date: datetime.date, end_date: datetime.date): def make_sflogs(mgroup: Mgroup, start_date: datetime.date, end_date: datetime.date, create_by=None):
for shift in Shift.objects.all(): shift_rule = mgroup.shift_rule
shifts = Shift.objects.filter(rule=shift_rule) # 根据排班规则制定排班记录
for shift in shifts:
start_time_o = shift.start_time_o start_time_o = shift.start_time_o
end_time_o = shift.end_time_o end_time_o = shift.end_time_o
current_date = start_date current_date = start_date
@ -26,12 +28,16 @@ def make_sflogs(mgroup: Mgroup, start_date: datetime.date, end_date: datetime.da
end_time = datetime.datetime.combine(current_date, end_time_o) end_time = datetime.datetime.combine(current_date, end_time_o)
if start_time > end_time: if start_time > end_time:
start_time -= datetime.timedelta(days=1) start_time -= datetime.timedelta(days=1)
duration = end_time - start_time
total_hours_now = duration.total_seconds() / 3600
SfLog.objects.get_or_create(mgroup=mgroup, shift=shift, start_time=start_time, defaults={ SfLog.objects.get_or_create(mgroup=mgroup, shift=shift, start_time=start_time, defaults={
"mgroup": mgroup, "mgroup": mgroup,
"shift": shift, "shift": shift,
"work_date": current_date,
"start_time": start_time, "start_time": start_time,
"end_time": end_time, "end_time": end_time,
"total_hour_now": 12 "total_hour_now": total_hours_now,
"create_by": create_by
}) })
current_date = current_date + datetime.timedelta(days=1) current_date = current_date + datetime.timedelta(days=1)

View File

@ -41,7 +41,8 @@ def get_total_hour_now(sflogId: str):
if sflogId: if sflogId:
sflog = SfLog.objects.get(id=sflogId) sflog = SfLog.objects.get(id=sflogId)
if sflog.end_time <= now: if sflog.end_time <= now:
sflog.total_hour_now = 12 # 写死的数据不是很好 sflog.total_hour_now = (
sflog.end_time-sflog.start_time).total_seconds()/3600 # 写死的数据不是很好
else: else:
total_hour_now = (now-sflog.start_time).total_seconds()/3600 total_hour_now = (now-sflog.start_time).total_seconds()/3600
sflog.total_hour_now = total_hour_now if total_hour_now > 0 else 0 sflog.total_hour_now = total_hour_now if total_hour_now > 0 else 0

View File

@ -1,7 +1,7 @@
from django.urls import path, include from django.urls import path, include
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from apps.wpm.views import SfLogViewSet, StLogViewSet, SfLogExpViewSet, WMaterialViewSet, MlogViewSet, HandoverViewSet from apps.wpm.views import SfLogViewSet, StLogViewSet, SfLogExpViewSet, WMaterialViewSet, MlogViewSet, HandoverViewSet, AttlogViewSet
API_BASE_URL = 'api/wpm/' API_BASE_URL = 'api/wpm/'
@ -14,6 +14,7 @@ router.register('sflogexp', SfLogExpViewSet, basename='sflogexp')
router.register('wmaterial', WMaterialViewSet, basename='wmaterial') router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
router.register('mlog', MlogViewSet, basename='mlog') router.register('mlog', MlogViewSet, basename='mlog')
router.register('handover', HandoverViewSet, basename='handover') router.register('handover', HandoverViewSet, basename='handover')
router.register('attlog', AttlogViewSet, basename='attlog')
urlpatterns = [ urlpatterns = [
path(API_BASE_URL, include(router.urls)), path(API_BASE_URL, include(router.urls)),
] ]

View File

@ -14,10 +14,10 @@ from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
from apps.utils.mixins import BulkCreateModelMixin from apps.utils.mixins import BulkCreateModelMixin
from .filters import SfLogExpFilter, SfLogFilter, WMaterialFilter, MlogFilter, HandoverFilter from .filters import SfLogExpFilter, SfLogFilter, WMaterialFilter, MlogFilter, HandoverFilter
from .models import SfLog, SfLogExp, StLog, WMaterial, Mlog, Handover, Mlogb from .models import SfLog, SfLogExp, StLog, WMaterial, Mlog, Handover, Mlogb, AttLog
from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer, from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer,
MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer, MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer,
GenHandoverSerializer, GenHandoverWmSerializer, MlogAnaSerializer) GenHandoverSerializer, GenHandoverWmSerializer, MlogAnaSerializer, AttLogSerializer)
from .services import mlog_submit, update_mtask, handover_submit from .services import mlog_submit, update_mtask, handover_submit
# Create your views here. # Create your views here.
@ -304,3 +304,12 @@ class HandoverViewSet(CustomModelViewSet):
create_by=user create_by=user
) )
return Response() return Response()
class AttlogViewSet(CustomModelViewSet):
queryset = AttLog.objects.all()
serializer_class = AttLogSerializer
select_related_fields = ['user', 'post', 'sflog']
filterset_fields = ['sflog__mgroup',
'sflog__mgroup__belong_dept__name', 'sflog__work_date', 'sflog__mgroup__cate', 'sflog__mgroup__need_enm']
ordering = ['-sflog__work_date', 'create_time']