diff --git a/apps/am/tasks.py b/apps/am/tasks.py index dbb4c849..da6061a9 100644 --- a/apps/am/tasks.py +++ b/apps/am/tasks.py @@ -7,22 +7,24 @@ import shapely.geometry @shared_task(base=CustomTask) -def cache_area_info(): +def cache_areas_info(): """ 缓存区域信息 """ - area_list = [] + area_fix_list = [] for i in Area.objects.filter(type=Area.AREA_TYPE_FIX).exclude(third_info__xx_rail=None): polygon = [] for item in i.third_info['xx_rail']['detail']['polygon']['points']: polygon.append([item.x, item.y]) poly_context = {'type': 'MULTIPOLYGON', - 'coordinates': [[area_list]]} + 'coordinates': [[area_fix_list]]} area_dict = { 'id': i.id, 'floor_no': i.third_info['xx_rail']['detail']['floorNo'], - 'poly_shape': shapely.geometry.asShape(poly_context) + 'poly_shape': shapely.geometry.asShape(poly_context), + 'stay_minute_min': i.stay_minute_min, + 'stay_minute_max': i.stay_minute_max } - area_list.append(area_dict) - cache.set('area_list', area_list, timeout=None) - return area_list + area_fix_list.append(area_dict) + cache.set('area_fix_list', area_fix_list, timeout=None) + return area_fix_list diff --git a/apps/ecm/service.py b/apps/ecm/service.py index 3ea5a326..b3f04abb 100644 --- a/apps/ecm/service.py +++ b/apps/ecm/service.py @@ -1,6 +1,7 @@ from apps.am.models import Access, Area +from apps.am.tasks import cache_areas_info from apps.hrm.models import Employee from apps.system.models import User from apps.third.clients import xxClient @@ -9,18 +10,27 @@ from apps.third.tapis import xxapis from apps.utils.queryset import get_child_queryset2 from django.core.cache import cache import time +import shapely.geometry -ep_loc_dict = { - "area_id": None, # 当前所在区域ID - "time1": None, # 首次在该区域时间戳 - "time2": None, # 当前在该区域时间戳 -} + +def get_area_info_from_cache(target: str, cache: list): + for i in cache: + if i['id'] == target: + return i + return None class EcmService: """事件处理服务 """ + ep_default_dict = { + 'area_fix_id': None, # 当前所在固定区域ID + 'time0': None, # 定位首次出现时间戳 + "time1": None, # 首次在该区域时间戳 + "time2": int(time.time()), # 当前时间戳 + } + def create_remind_and_speak(cls): """ 创建事件提醒并发送短信/微信/音响 @@ -77,6 +87,16 @@ class EcmService: # 找到进入对象 blts = TDevice.objects.filter(code=data['userId']).first() if area and blts and blts.employee: # 如果是人 + if area.type == Area.AREA_TYPE_FIX: + # 更新人员位置信息缓存 + key_str = f'ep_{blts.employee.id}' + ep_loc_dict = cache.get_or_set( + key_str, cls.ep_default_dict, timeout=None + ) + if ep_loc_dict['area_fix_id'] != area.id: # 如果区域未变化则不动 + ep_loc_dict['time1'] = ep_loc_dict['time2'] + ep_loc_dict['area_fix_id'] = area.id + cache.set(key_str, ep_loc_dict) ep_blt = blts.employee # 标签绑定人员 if ep_blt: for i in Access.objects.filter(area=area).order_by('sort'): @@ -142,14 +162,38 @@ class EcmService: def loc_change(cls, data): blts = TDevice.objects.filter(code=data['userId']).first() if blts.employee: - # 查询当前所在区域 + # 从缓存查询人员位置信息 time2 = int(time.time()) key_str = f'ep_{blts.employee.id}' - ep_default_dict = { - "area": None, # 当前所在区域 - "time1": None, # 首次在该区域时间戳 - "time2": time2, # 当前在该区域时间戳 - } ep_loc_dict = cache.get_or_set( - key_str, ep_default_dict, 60*60*24*7 - ) \ No newline at end of file + key_str, cls.ep_default_dict, timeout=None + ) + ep_loc_dict['time2'] = time2 + # 从缓存里获取固定区域列表信息 + area_fix_list = cache.get('area_fix_list', None) + if not area_fix_list: + area_fix_list = cache_areas_info() + if ep_loc_dict.get('area_fix_id', None): + # 如果存在所在固定区域 + area_info = get_area_info_from_cache(ep_loc_dict['area_fix_id'], area_fix_list) + if area_info: + # 在该固定区域停留时间(分钟) + stay_minute = int((ep_loc_dict['time2']-ep_loc_dict['time1'])/60) + # 判断停留时间是否合理 + # 先通过自定义权限过滤(暂未做) + # 再经过通用设置过滤 + if 0 < stay_minute < area_info['stay_minute_min']: + # 触发离岗事件 + return + elif area_info['stay_minute_max'] < stay_minute: + # 触发超时滞留事件 + return + else: + for i in area_fix_list: + if data['floorNo'] == i['floor_no']: + point = shapely.geometry.Point(data['xMillimeter'], data['yMillimeter']) + if i['poly_shape'].intersects(point): # 如果点在多边形中 + ep_loc_dict['time1'] = time2 + ep_loc_dict['are_id'] = i['area_fix_id'] + ep_loc_dict['time2'] = time2 + cache.set(key_str, ep_loc_dict) diff --git a/apps/ecm/tasks.py b/apps/ecm/tasks.py index 70c4c647..851b4296 100644 --- a/apps/ecm/tasks.py +++ b/apps/ecm/tasks.py @@ -27,4 +27,4 @@ def cal_area_count(): # 触发缺员事件 i.count_people_min = total_count i.save() - pass + pass \ No newline at end of file diff --git a/apps/ecm/urls.py b/apps/ecm/urls.py index a43544ab..b70da6a6 100644 --- a/apps/ecm/urls.py +++ b/apps/ecm/urls.py @@ -1,4 +1,4 @@ -from apps.am.tasks import cache_area_info +from apps.am.tasks import cache_areas_info from apps.ecm.views import EventCateViewSet, NotifySettingViewSet, EventViewSet, RemindViewSet from django.urls import path, include from rest_framework.routers import DefaultRouter @@ -6,7 +6,7 @@ from rest_framework.routers import DefaultRouter API_BASE_URL = 'api/ecm/' HTML_BASE_URL = 'ecm/' -cache_area_info() # 首先缓存区域信息 +cache_areas_info() # 首先缓存区域信息 router = DefaultRouter() router.register('event_cate', EventCateViewSet, basename='event_cate') router.register('event', EventViewSet, basename='event') diff --git a/apps/rpm/views.py b/apps/rpm/views.py index 4d0f1f1c..a55f5404 100644 --- a/apps/rpm/views.py +++ b/apps/rpm/views.py @@ -160,7 +160,7 @@ class RpjmemberViewSet(CustomModelViewSet): def destroy(self, request, *args, **kwargs): obj = self.get_object() - if obj.rpj.state == Rpj.RPJ_CREATE: + if obj.rpj.state != Rpj.RPJ_CREATE: raise ParseError('项目非创建状态不可删除') return super().destroy(request, *args, **kwargs) @@ -177,12 +177,12 @@ class RpjfileViewSet(UpdateModelMixin, DestroyModelMixin, ListModelMixin, Custom def update(self, request, *args, **kwargs): obj = self.get_object() - if obj.rpj.state == Rpj.RPJ_CREATE: + if obj.rpj.state != Rpj.RPJ_CREATE: raise ParseError('项目非创建状态不可修改') return super().update(request, *args, **kwargs) def destroy(self, request, *args, **kwargs): obj = self.get_object() - if obj.rpj.state == Rpj.RPJ_CREATE: + if obj.rpj.state != Rpj.RPJ_CREATE: raise ParseError('项目非创建状态不可删除') return super().destroy(request, *args, **kwargs)