diff --git a/apps/am/migrations/0006_auto_20220627_0836.py b/apps/am/migrations/0006_auto_20220627_0836.py new file mode 100644 index 00000000..dd3eaf29 --- /dev/null +++ b/apps/am/migrations/0006_auto_20220627_0836.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.12 on 2022-06-27 00:36 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('hrm', '0002_auto_20220617_1124'), + ('system', '0005_auto_20220627_0836'), + ('am', '0005_auto_20220625_1631'), + ] + + operations = [ + migrations.RemoveField( + model_name='access', + name='obj', + ), + migrations.AddField( + model_name='access', + name='dept', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='system.dept', verbose_name='关联部门'), + ), + migrations.AddField( + model_name='access', + name='employee', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='hrm.employee', verbose_name='关联人员'), + ), + migrations.AddField( + model_name='access', + name='post', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='system.post', verbose_name='关联岗位'), + ), + migrations.AddField( + model_name='access', + name='sort', + field=models.PositiveSmallIntegerField(default=1, verbose_name='排序'), + ), + migrations.AddField( + model_name='access', + name='stay_minute_max', + field=models.PositiveSmallIntegerField(default=0, verbose_name='最长停留时间'), + ), + migrations.AddField( + model_name='access', + name='stay_minute_min', + field=models.PositiveSmallIntegerField(default=0, verbose_name='最短停留时间'), + ), + migrations.AddField( + model_name='area', + name='stay_minute_max', + field=models.PositiveSmallIntegerField(default=0, help_text='0代表未配置', verbose_name='最长停留时间'), + ), + migrations.AddField( + model_name='area', + name='stay_minute_min', + field=models.PositiveSmallIntegerField(default=0, help_text='0代表未配置', verbose_name='最短停留时间'), + ), + migrations.AlterField( + model_name='access', + name='obj_cate', + field=models.CharField(help_text='post/dept/people', max_length=20, verbose_name='对象类型'), + ), + migrations.AlterField( + model_name='area', + name='employee_yes', + field=models.BooleanField(default=True, verbose_name='准许内部员工'), + ), + ] diff --git a/apps/am/models.py b/apps/am/models.py index 2e410c55..a1ba523d 100755 --- a/apps/am/models.py +++ b/apps/am/models.py @@ -1,6 +1,6 @@ from django.db import models from apps.hrm.models import Employee -from apps.system.models import Post, User +from apps.system.models import Dept, Post, User from apps.utils.constants import ObjCate from apps.utils.models import CommonADModel, CommonBModel # Create your models here. @@ -33,10 +33,12 @@ class Area(CommonBModel): number = models.CharField('编号', max_length=20, null=True, blank=True) visitor_yes = models.BooleanField('准许访客人员', default=False) remployee_yes = models.BooleanField('准许相关方人员', default=False) - employee_yes = models.BooleanField('准许全部员工', default=True) + employee_yes = models.BooleanField('准许内部员工', default=True) count_people_min = models.PositiveIntegerField('最小人员数', default=0) count_people_max = models.PositiveIntegerField('最大人员数', default=1000) count_people = models.PositiveIntegerField('当前人数', default=0) + stay_minute_min = models.PositiveSmallIntegerField('最短停留时间', default=0, help_text='0代表未配置') + stay_minute_max = models.PositiveSmallIntegerField('最长停留时间', default=0, help_text='0代表未配置') is_hidden = models.BooleanField('隐藏围栏用', default=False) third_info = models.JSONField('三方信息', default=dict, null=False, blank=True) @@ -59,6 +61,10 @@ class Access(CommonADModel): type = models.PositiveSmallIntegerField('准入类型', choices=ACCESS_CHOICE) area = models.ForeignKey(Area, verbose_name='关联区域', on_delete=models.CASCADE) - obj_cate = models.CharField('对象类型', max_length=20, help_text='employee/post') - obj = models.CharField('关联对象', unique=True, max_length=50, null=True, blank=True) + obj_cate = models.CharField('对象类型', max_length=20, help_text='post/dept/people') + post = models.ForeignKey(Post, verbose_name='关联岗位', on_delete=models.CASCADE, null=True, blank=True) + dept = models.ForeignKey(Dept, verbose_name='关联部门', on_delete=models.CASCADE, null=True, blank=True) + employee = models.ForeignKey(Employee, verbose_name='关联人员', on_delete=models.CASCADE, null=True, blank=True) + stay_minute_min = models.PositiveSmallIntegerField('最短停留时间', default=0) + stay_minute_max = models.PositiveSmallIntegerField('最长停留时间', default=0) sort = models.PositiveSmallIntegerField('排序', default=1) diff --git a/apps/am/serializers.py b/apps/am/serializers.py index df6871e1..3a9c6d86 100644 --- a/apps/am/serializers.py +++ b/apps/am/serializers.py @@ -3,7 +3,7 @@ from apps.am.models import Access, Area from apps.hrm.models import Employee from apps.system.models import Post from apps.utils.serializers import CustomModelSerializer -from apps.system.serializers import PostSimpleSerializer +from rest_framework.exceptions import ParseError class AreaSimpleSerializer(CustomModelSerializer): @@ -28,7 +28,27 @@ class AreaCreateUpdateSerializer(CustomModelSerializer): class AccessCreateSerializer(CustomModelSerializer): class Meta: model = Access - fields = ['type', 'area', 'obj_cate', 'obj'] + fields = ['type', 'area', 'obj_cate', 'post', 'employee'] + + def create(self, validated_data): + post = validated_data.get('post', None) + dept = validated_data.get('dept', None) + employee = validated_data.get('employee', None) + if post: + validated_data['obj_cate'] = 'post' + validated_data['employee'] = None + validated_data['dept'] = None + elif dept: + validated_data['obj_cate'] = 'dept' + validated_data['post'] = None + validated_data['employee'] = None + elif employee: + validated_data['obj_cate'] = 'people' + validated_data['post'] = None + validated_data['dept'] = None + else: + raise ParseError('请指定岗位或部门或具体人员') + return super().create(validated_data) class AccessSerializer(CustomModelSerializer): diff --git a/apps/am/views.py b/apps/am/views.py index e0a4d221..47a37ad6 100755 --- a/apps/am/views.py +++ b/apps/am/views.py @@ -16,6 +16,7 @@ class AreaViewSet(CustomModelViewSet): create_serializer_class = AreaCreateUpdateSerializer update_serializer_class = AreaCreateUpdateSerializer serializer_class = AreaSerializer + ordering = ['number'] @transaction.atomic @action(methods=['post'], detail=True, perms_map={'post': 'area:bind_rail'}, diff --git a/apps/ecm/service.py b/apps/ecm/service.py index 7396e493..87302530 100644 --- a/apps/ecm/service.py +++ b/apps/ecm/service.py @@ -34,7 +34,7 @@ class EcmService: cls.rail_in(data=data.data) elif data.data.type == 2: # 围栏离开 - pass + cls.rail_out(data=data.data) elif data.type == 'onKeyAlarm': # 一键呼救 pass @@ -60,44 +60,42 @@ class EcmService: def rail_in(cls, data): """围栏进入事件 """ - # 判断区域是否超员 + # 找到所在围栏 area = Area.objects.filter(third_info__xx_rail__id=data['railId']).first() - # 判断进入对象 + # 找到进入对象 blts = TDevice.objects.filter(code=data['userId']).first() - if blts and blts.obj_cate == 'employee': # 如果是人 - if area and area.type == Area.AREA_TYPE_FIX: # 如果是固定区域 - json = {"railId": data['railId'], "type": ""} - _, res = xxClient.request(**xxapis['rail_ibeacon_list'], json=json) - total_count = res['totalCount'] - if total_count >= area.count_people_max: - # 触发超员事件 - area.count_people = total_count - area.save() - pass - elif total_count < area.count_people_min: - # 触发缺员事件 - area.count_people_min = total_count - area.save() - pass - ep_blts = Employee.objects.filter(id=blts.obj).first() # 标签绑定人员 + if blts and blts.employee: # 如果是人 + ep_blts = blts.employee # 标签绑定人员 if ep_blts: - # 判断有无进入权限 进行匹配 + for i in Access.objects.filter(area=area).order_by('sort'): + # 优先自定义权限过滤 + if i.post: # 如果是按岗位设定的 + eps_access = Employee.objects.filter(user__posts=i.post) + if ep_blts in eps_access and i.type == Access.ACCESS_IN_YES: + return + elif ep_blts in eps_access and i.type == Access.ACCESS_IN_NO: + # 触发非法进入事件 + pass + elif i.employee: # 如果是按人设定的 + if ep_blts == i.employee and i.type == Access.ACCESS_IN_YES: + return + elif ep_blts == i.employee and i.type == Access.ACCESS_IN_NO: + # 触发非法进入事件 + pass + # 通用权限设置过滤 if ep_blts.type == 'employee' and area.employee_yes: return elif ep_blts.type == 'remployee' and area.remployee_yes: return elif ep_blts.type == 'visitor' and area.visitor_yes: return - for i in Access.objects.filter(area=area).order_by('sort'): - if i.obj_cate == 'employee': - ep_acess = Employee.objects.filter(id=i.obj).first() - if ep_blts == ep_acess and i.type == 10: - return - elif ep_blts == ep_acess and i.type == 20: - # 触发非法进入事件 - pass - elif i.obj_cate == 'post': - pass + else: + # 触发非法进入事件 + pass else: # 触发未知标签进入事件 - pass \ No newline at end of file + pass + + @classmethod + def rail_out(cls, data): + pass diff --git a/apps/ecm/tasks.py b/apps/ecm/tasks.py index e69de29b..70c4c647 100644 --- a/apps/ecm/tasks.py +++ b/apps/ecm/tasks.py @@ -0,0 +1,30 @@ +from __future__ import absolute_import, unicode_literals + +from celery import shared_task + +from apps.am.models import Area +from apps.third.clients import xxClient +from apps.third.tapis import xxapis + + +@shared_task +def cal_area_count(): + """ + 计算区域内人员数量 + """ + for i in Area.objects.filter(type=Area.AREA_TYPE_FIX): + if i.third_info.get('xx_rail', None): + railId = i.third_info['xx_rail']['id'] + json = {"railId": railId, "type": ""} + _, res = xxClient.request(**xxapis['rail_ibeacon_list'], json=json) + total_count = res['totalCount'] + if total_count >= i.count_people_max: + # 触发超员事件 + i.count_people = total_count + i.save() + pass + elif total_count < i.count_people_min: + # 触发缺员事件 + i.count_people_min = total_count + i.save() + pass diff --git a/apps/system/migrations/0005_auto_20220627_0836.py b/apps/system/migrations/0005_auto_20220627_0836.py new file mode 100644 index 00000000..7abe5d5a --- /dev/null +++ b/apps/system/migrations/0005_auto_20220627_0836.py @@ -0,0 +1,30 @@ +# Generated by Django 3.2.12 on 2022-06-27 00:36 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0004_alter_userpost_unique_together'), + ] + + operations = [ + migrations.AlterField( + model_name='userpost', + name='dept', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='up_dept', to='system.dept'), + ), + migrations.AlterField( + model_name='userpost', + name='post', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='up_post', to='system.post'), + ), + migrations.AlterField( + model_name='userpost', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='up_user', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/apps/system/models.py b/apps/system/models.py index d327a186..5d4e8475 100755 --- a/apps/system/models.py +++ b/apps/system/models.py @@ -147,9 +147,9 @@ class UserPost(BaseModel): 用户岗位关系表 """ name = models.CharField('名称', max_length=20, null=True, blank=True) - user = models.ForeignKey(User, on_delete=models.CASCADE) - post = models.ForeignKey(Post, on_delete=models.CASCADE) - dept = models.ForeignKey(Dept, on_delete=models.CASCADE) + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='up_user') + post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='up_post') + dept = models.ForeignKey(Dept, on_delete=models.CASCADE, related_name='up_dept') sort = models.PositiveSmallIntegerField('排序', default=1) class Meta: diff --git a/apps/third/models.py b/apps/third/models.py index 80e0dd69..2e744ca4 100755 --- a/apps/third/models.py +++ b/apps/third/models.py @@ -1,6 +1,7 @@ from django.db import models from apps.am.models import Area import uuid +from apps.hrm.models import Employee from apps.utils.constants import ObjCate from apps.utils.models import BaseModel @@ -38,8 +39,8 @@ class TDevice(BaseModel): verbose_name='所在区', null=True, blank=True) areas = models.ManyToManyField(Area, verbose_name='覆盖区', related_name='tareas') - obj_cate = models.CharField('对象类型', max_length=20, help_text='employee/...') - obj = models.CharField('绑定对象', unique=True, max_length=50, null=True, blank=True) + obj_cate = models.CharField('绑定对象', max_length=20, help_text='people/...') + employee = models.ForeignKey(Employee, verbose_name='绑定人员', on_delete=models.CASCADE, null=True, blank=True) is_clock = models.BooleanField('是否打卡设备', default=False) third_info = models.JSONField('三方信息', default=dict, null=False, blank=True)