feat: wpm中增加到岗记录
This commit is contained in:
parent
cbce572350
commit
fddadfe30c
|
@ -57,6 +57,7 @@ class PmService:
|
|||
"""
|
||||
从大任务自动排产出小任务
|
||||
"""
|
||||
from apps.wpm.services import make_sflogs
|
||||
if utask.state != Utask.UTASK_CREATED:
|
||||
raise ParseError('任务状态异常')
|
||||
utask.state = Utask.UTASK_DECOMPOSE
|
||||
|
@ -82,6 +83,8 @@ class PmService:
|
|||
'update_by': user,
|
||||
'is_count_utask': True
|
||||
})
|
||||
make_sflogs(mgroup=utask.mgroup,
|
||||
start_date=task_date, end_date=task_date, create_by=user)
|
||||
else:
|
||||
# 获取产品的加工路线
|
||||
rqs = Route.get_routes(product)
|
||||
|
@ -131,6 +134,8 @@ class PmService:
|
|||
'update_by': user,
|
||||
'is_count_utask': val.is_count_utask
|
||||
})
|
||||
make_sflogs(mgroup=mgroup,
|
||||
start_date=task_date, end_date=task_date, create_by=user)
|
||||
|
||||
@classmethod
|
||||
def check_orderitems(cls, orderitems: QuerySet[OrderItem]):
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
),
|
||||
]
|
|
@ -32,6 +32,7 @@ class SfLog(CommonADModel):
|
|||
Shift, verbose_name='当班班次', on_delete=models.CASCADE)
|
||||
leader = models.ForeignKey(
|
||||
'system.user', verbose_name='班长', on_delete=models.CASCADE, null=True, blank=True)
|
||||
work_date = models.DateField('值班日期', null=True, blank=True)
|
||||
start_time = models.DateTimeField('值班开始')
|
||||
end_time = models.DateTimeField('值班结束')
|
||||
note = models.TextField('其他备注', null=True, blank=True)
|
||||
|
@ -179,3 +180,27 @@ class Handover(CommonADModel):
|
|||
submit_time = models.DateTimeField('提交时间', null=True, blank=True)
|
||||
submit_user = models.ForeignKey(
|
||||
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)
|
||||
|
|
|
@ -3,13 +3,15 @@ from apps.utils.serializers import CustomModelSerializer
|
|||
from rest_framework import serializers
|
||||
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.serializers import UserSimpleSerializer
|
||||
from apps.pm.models import Mtask
|
||||
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 django.db import transaction
|
||||
from django.utils import timezone
|
||||
|
||||
|
||||
class StLogSerializer(CustomModelSerializer):
|
||||
|
@ -37,16 +39,26 @@ class SfLogSerializer(CustomModelSerializer):
|
|||
}
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
old_pcoal_heat = instance.pcoal_heat
|
||||
old_team = instance.team
|
||||
instance = super().update(instance, validated_data)
|
||||
new_pcoal_heat = instance.pcoal_heat
|
||||
new_team = instance.team
|
||||
if new_pcoal_heat != old_pcoal_heat:
|
||||
cal_enstat_when_pcoal_heat_change.delay(instance.id)
|
||||
if new_team != old_team:
|
||||
cal_enstat_when_team_change.delay(instance.id)
|
||||
return instance
|
||||
with transaction.atomic():
|
||||
old_pcoal_heat = instance.pcoal_heat
|
||||
old_team = instance.team
|
||||
instance: SfLog = super().update(instance, validated_data)
|
||||
new_pcoal_heat = instance.pcoal_heat
|
||||
new_team = instance.team
|
||||
mgroup: Mgroup = instance.mgroup
|
||||
if new_pcoal_heat != old_pcoal_heat and mgroup.need_enm:
|
||||
cal_enstat_when_pcoal_heat_change.delay(instance.id)
|
||||
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):
|
||||
# if hasattr(self.Meta, 'update_fields') and self.context['request'].method in ['PUT', 'PATCH']:
|
||||
# u_fields = self.Meta.update_fields
|
||||
|
@ -111,6 +123,8 @@ class MlogSerializer(CustomModelSerializer):
|
|||
source='equipment.name', read_only=True)
|
||||
equipment_2_name = serializers.CharField(
|
||||
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)
|
||||
mlogb = MlogbSerializer(
|
||||
label='多产出件信息', many=True, required=False)
|
||||
|
@ -251,3 +265,16 @@ class MlogAnaSerializer(serializers.Serializer):
|
|||
start_date = serializers.DateField(label='开始日期', required=True)
|
||||
end_date = serializers.DateField(label='结束日期', required=True)
|
||||
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__'
|
||||
|
|
|
@ -16,8 +16,10 @@ from apps.mtm.models import Mgroup, Shift, Material, Route
|
|||
from .models import SfLog, SfLogExp, WMaterial, Mlog, Mlogb, Handover
|
||||
|
||||
|
||||
def make_sflogs(mgroup: Mgroup, start_date: datetime.date, end_date: datetime.date):
|
||||
for shift in Shift.objects.all():
|
||||
def make_sflogs(mgroup: Mgroup, start_date: datetime.date, end_date: datetime.date, create_by=None):
|
||||
shift_rule = mgroup.shift_rule
|
||||
shifts = Shift.objects.filter(rule=shift_rule) # 根据排班规则制定排班记录
|
||||
for shift in shifts:
|
||||
start_time_o = shift.start_time_o
|
||||
end_time_o = shift.end_time_o
|
||||
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)
|
||||
if start_time > end_time:
|
||||
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={
|
||||
"mgroup": mgroup,
|
||||
"shift": shift,
|
||||
"work_date": current_date,
|
||||
"start_time": start_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)
|
||||
|
||||
|
|
|
@ -41,7 +41,8 @@ def get_total_hour_now(sflogId: str):
|
|||
if sflogId:
|
||||
sflog = SfLog.objects.get(id=sflogId)
|
||||
if sflog.end_time <= now:
|
||||
sflog.total_hour_now = 12 # 写死的数据不是很好
|
||||
sflog.total_hour_now = (
|
||||
sflog.end_time-sflog.start_time).total_seconds()/3600 # 写死的数据不是很好
|
||||
else:
|
||||
total_hour_now = (now-sflog.start_time).total_seconds()/3600
|
||||
sflog.total_hour_now = total_hour_now if total_hour_now > 0 else 0
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.urls import path, include
|
||||
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/'
|
||||
|
@ -14,6 +14,7 @@ router.register('sflogexp', SfLogExpViewSet, basename='sflogexp')
|
|||
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
|
||||
router.register('mlog', MlogViewSet, basename='mlog')
|
||||
router.register('handover', HandoverViewSet, basename='handover')
|
||||
router.register('attlog', AttlogViewSet, basename='attlog')
|
||||
urlpatterns = [
|
||||
path(API_BASE_URL, include(router.urls)),
|
||||
]
|
||||
|
|
|
@ -14,10 +14,10 @@ from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
|||
from apps.utils.mixins import BulkCreateModelMixin
|
||||
|
||||
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,
|
||||
MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer,
|
||||
GenHandoverSerializer, GenHandoverWmSerializer, MlogAnaSerializer)
|
||||
GenHandoverSerializer, GenHandoverWmSerializer, MlogAnaSerializer, AttLogSerializer)
|
||||
from .services import mlog_submit, update_mtask, handover_submit
|
||||
# Create your views here.
|
||||
|
||||
|
@ -304,3 +304,12 @@ class HandoverViewSet(CustomModelViewSet):
|
|||
create_by=user
|
||||
)
|
||||
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']
|
||||
|
|
Loading…
Reference in New Issue