def remove_expired_notifications(): print('Cleaning expired notifications...') # удаляем старые шаблоны уведомлений notifications = Notification.objects\ .filter(expired_at__lt=utcnow())\ .select_related('job', 'job__user') session_cache = {} i = 0 for notification in notifications.iterator(): user = notification.job.user if user not in session_cache: sess_id = get_wialon_session_key(user) session_cache[user] = sess_id else: sess_id = session_cache[user] try: remove_notification(notification, user, sess_id) except WialonException as e: print(e) else: notification.delete() i += 1 for user, sess_id in session_cache.items(): logout_session(user, sess_id) print('%s expired notifications removed' % i)
def post(self, request, *args, **kwargs): doc = request.data.xpath('/routesRequest') if len(doc) < 1: return error_response('Не найден объект routesRequest', code='routesRequest_not_found') doc = doc[0] doc_id = doc.get('idDoc', '') if not doc_id: return error_response('Не указан параметр idDoc', code='idDoc_not_found') try: org_id = int(doc.get('idOrg', '')) except ValueError: org_id = 0 sess_id = get_wialon_session_key(request.user) try: routes = get_routes(sess_id) except APIProcessError as e: return error_response(str(e), code=e.code) finally: logout_session(request.user, sess_id) context = self.get_context_data(**kwargs) context.update({ 'doc_id': doc_id, 'create_date': utcnow(), 'routes': routes, 'org_id': org_id }) return XMLResponse('ura/routes.xml', context)
def email_reports(): print('Mailing monthly driving style total report...') reports = models.DrivingStyleTotalReportDelivery.objects.published() now = utcnow() for report in reports: print('Monthly VCHM Driving style total report %s' % report) for user in report.users.all(): local_now = utc_to_local_time(now, user.timezone) if not user.email: print('Skipping user %s (no email)' % user) continue print('User %s' % user) sess_id = None try: # получаем отчеты через HTTP sess_id = get_wialon_session_key(user) # если время выполнения - 1е число месяца, то отчет сформируется за прошлый месяц, # иначе отчет подготовится за текущий месяц вчерашний день включительно. date_to = (local_now - datetime.timedelta(days=1)).date() date_from = date_to.replace(day=1) res = make_report(report, user, sess_id, date_from=date_from, date_to=date_to, attempts=0) filename = 'total_vchm_driving_report_%s.xls' % user.pk log = models.ReportEmailDeliveryLog( user=user, email=user.email, report_type=EmailDeliveryReportTypeEnum.DRIVING_STYLE, subject='Сводный отчет о качестве вождения (ВЧМ)', body='Здравствуйте, %s. Отчет по вложении.' % user.full_name) content = ContentFile(res.content) log.report.save(filename, content, save=False) log.save() log.send(reraise=True) except Exception as e: print('Error: %s' % e) send_trigger_email('Ошибка в работе системы рассылки отчетов', extra_data={ 'Exception': str(e), 'Traceback': traceback.format_exc(), 'report': report, 'user': user }) finally: if sess_id: logout_session(user, sess_id)
def forwards_func(apps, schema_editor): job_model = apps.get_model('ura', 'UraJob') user_model = apps.get_model('users', 'User') orgs = user_model.objects.filter(is_active=True, supervisor__isnull=False) units_cache = {} routes_cache = {} for org in orgs.iterator(): print('Organization %s' % org.username) sess_id = get_wialon_session_key(org) units = get_units(sess_id) units_cache[org.pk] = { u['id']: '%s (%s) [%s]' % (u['name'], u['number'], u['vin']) for u in units } routes = get_routes(sess_id) logout_session(org, sess_id) routes_cache[org.pk] = {r['id']: r['name'] for r in routes} sess_id = None print('Jobs count: %s' % job_model.objects.count()) i = 0 for job in job_model.objects.iterator(): i += 1 if not job.user_id: print('%s: Job %s missed due to lack of user' % (i, job.pk)) continue unit_title = route_title = None try: unit_id = int(job.unit_id) unit_title = units_cache.get(job.user_id, {}).get(unit_id) if unit_title: job.unit_title = unit_title except (ValueError, TypeError, AttributeError): pass try: route_id = int(job.route_id) route_title = routes_cache.get(job.user_id, {}).get(route_id) if route_title: job.route_title = route_title except (ValueError, TypeError, AttributeError): pass if unit_title or route_title: job.save() print('%s: unit=%s, route=%s (%s)' % (i, unit_title, route_title, job.created))
def get(self, request, **kwargs): now = utc_to_local_time(utcnow(), request.user.timezone) local_dt_from = now.replace(hour=0, minute=0, second=0) local_dt_to = now.replace(hour=23, minute=59, second=59) user = User.objects.get(pk=1) sess_id = get_wialon_session_key(user) moving_service = self.service_class( user=user, local_dt_from=local_dt_from, local_dt_to=local_dt_to, sess_id=sess_id ) moving_service.exec_report() moving_service.analyze() logout_session(user, sess_id) return success_response()
def post(self, request, **kwargs): units = [] context = self.get_context_data(**kwargs) context.update({'now': utcnow(), 'units': units}) units_els = request.data.xpath('/getMoving/unit') if not units_els: logout_session(request.user, self.sess_id) return error_response('Не указаны объекты типа unit', code='units_not_found') self.get_geozones_report_template_id() for unit_el in units_els: self.get_input_data(unit_el) self.unit_id = int(self.input_data.get('unit_id')) self.get_job() self.get_route() self.get_report_data() self.get_object_messages() self.ride_points = [] unit_info = { 'id': self.unit_id, 'date_begin': utc_to_local_time(self.input_data['date_begin'], request.user.timezone), 'date_end': utc_to_local_time(self.input_data['date_end'], request.user.timezone), 'points': self.ride_points } self.prepare_geozones_visits() self.process_messages() self.report_post_processing(unit_info) self.update_job_points_cache() self.prepare_output_data() units.append(unit_info) logout_session(request.user, self.sess_id) return XMLResponse('ura/moving.xml', context)
def post(self, request, **kwargs): jobs = [] print('Start getRaces:\n' + str(request.body)) context = self.get_context_data(**kwargs) context.update({ 'now': utcnow(), 'jobs': jobs }) jobs_els = request.data.xpath('/getRaces/job') if not jobs_els: logout_session(request.user, self.sess_id) return error_response('Не указаны объекты типа job', code='jobs_not_found') self.get_geozones_report_template_id() for job_el in jobs_els: self.get_input_data(job_el) self.unit_id = int(self.input_data.get('unit_id')) self.get_job() self.get_route() self.points_dict_by_name = {x['name']: x['id'] for x in self.route['points']} self.get_report_data() self.get_object_messages() self.prepare_geozones_visits() self.ride_points = [] self.process_messages() races = [] job_info = { 'obj': self.job, 'races': races } self.make_races(races) self.report_post_processing(job_info) self.prepare_output_data(job_info) jobs.append(job_info) logout_session(request.user, self.sess_id) return XMLResponse('ura/races.xml', context)
def email_reports(period=None): print('Mailing %s driving style report...' % period) if not period or period not in ('daily', 'weekly', 'monthly'): print('Period not specified') return reports = models.DrivingStyleReportDelivery.objects.published() period_verbose = '' if period == 'daily': period_verbose = 'Ежедневный' reports = reports.filter(is_daily=True) elif period == 'weekly': period_verbose = 'Еженедельный' reports = reports.filter(is_weekly=True) elif period == 'monthly': period_verbose = 'Ежемесячный' reports = reports.filter(is_monthly=True) now = utcnow() for report in reports: print('%s VCHM Driving style report %s' % (period, report)) for user in report.users.all(): local_now = utc_to_local_time(now, user.timezone) if not user.email: print('Skipping user %s (no email)' % user) continue if local_now.hour != SEND_HOUR: print('Skipping user %s (%s != %s)' % (user, local_now.hour, SEND_HOUR)) continue print('User %s' % user) sess_id = None try: # получаем отчеты через HTTP sess_id = get_wialon_session_key(user) date_from = date_to = (local_now - datetime.timedelta(days=1)).date() if period == 'daily': date_from = date_to elif period == 'weekly': date_from = (local_now - datetime.timedelta(days=7)).date() elif period == 'monthly': date_from = date_to.replace(day=1) res = make_report(report, user, sess_id, date_from=date_from, date_to=date_to, attempts=0) filename = '%s_vchm_driving_report_%s.xls' % (period, user.pk) log = models.ReportEmailDeliveryLog( user=user, email=user.email, report_type=EmailDeliveryReportTypeEnum.DRIVING_STYLE, subject='%s отчет о качестве вождения (ВЧМ)' % period_verbose, body='Здравствуйте, %s. Отчет по вложении.' % user.full_name) content = ContentFile(res.content) log.report.save(filename, content) log.save() log.send(reraise=True) except Exception as e: print('Error: %s' % e) send_trigger_email('Ошибка в работе системы рассылки отчетов', extra_data={ 'Exception': str(e), 'Traceback': traceback.format_exc(), 'report': report, 'user': user }) finally: if sess_id: logout_session(user, sess_id)
def cache_geozones(): print('Caching geozones...') with transaction.atomic(): i = 1 users = User.objects.filter(supervisor__isnull=False, wialon_username__isnull=False, wialon_password__isnull=False).exclude( wialon_username='', wialon_password='') print('%s users found' % len(users)) for user in users: sess_id = get_wialon_session_key(user) print('%s) User %s processing' % (i, user)) routes = get_routes(sess_id, with_points=True) logout_session(user, sess_id) del sess_id print('%s routes found' % len(routes)) for route in routes: print('Route %s' % route['name']) name = route['name'].strip() job_template, created = StandardJobTemplate.objects.get_or_create( wialon_id=str(route['id']), defaults={ 'title': name, 'user': user }) existing_points = set() if not created: if job_template.title != name: job_template.title = name job_template.user = user job_template.save() existing_points = {p for p in job_template.points.all()} # убираем дубли (когда одна и та же геозона дублируется в маршруте) route['points'] = {r['id']: r for r in route['points']}.values() print('%s points found, already exist: %s' % (len(route['points']), len(existing_points))) for point in route['points']: name = point['name'].strip() standard_point, created = StandardPoint.objects.get_or_create( job_template=job_template, wialon_id=str(point['id']), defaults={'title': name}) if not created: existing_points.discard(standard_point) if standard_point.title != name: standard_point.title = name standard_point.save() if existing_points: print('Points to remove: %s' % ', '.join([str(x) for x in existing_points])) for existing_point in existing_points: existing_point.delete() sleep(.3) i += 1
def exec_report(user, template_id, sess_id, dt_from, dt_to, report_resource_id=None, object_id=None, attempts=3): if report_resource_id is None: error = 'не выявлено' try: report_resource_id = get_wialon_report_resource_id(user, sess_id) except WialonException as e: error = e if not report_resource_id: raise ReportException( 'Не удалось получить ID ресурса для пользователя %s ' '(наименование ресурса: %s). Ошибка: %s' % (str(user), user.wialon_resource_name, error)) if object_id is None: error = 'не выявлено' try: object_id = get_wialon_report_object_id(user, sess_id) except WialonException as e: error = e if not object_id: raise ReportException( 'Не удалось получить ID группового объекта для пользователя %s ' '(наименование группового объекта: %s). Ошибка: %s' % (str(user), user.wialon_group_object_name, error)) # замедляем в случае чего, для прохождения лимита throttle_report(user) r = requests.post( settings.WIALON_BASE_URL + '?svc=report/exec_report&sid=' + sess_id, { 'params': json.dumps({ 'reportResourceId': report_resource_id, 'reportTemplateId': template_id, 'reportTemplate': None, 'reportObjectId': object_id, 'reportObjectSecId': 0, 'interval': { 'flags': 0, 'from': dt_from, 'to': dt_to } }), 'sid': sess_id }) result = load_requests_json(r) if 'error' in result: # сессия неожиданно устарела (такое очень редко и необъяснимо бывает) - отправляем еще раз if result['error'] == 1: if attempts > 1: # генерируем новую сессию sess_id = get_wialon_session_key(user, invalidate=True) result = exec_report(user, template_id, sess_id, dt_from, dt_to, report_resource_id=report_resource_id, object_id=object_id, attempts=attempts - 1) logout_session(user, sess_id) return result raise ReportException(WIALON_SESSION_EXPIRED) raise ReportException(WIALON_INTERNAL_EXCEPTION % result) return result
def post(self, request, *args, **kwargs): jobs = [] jobs_els = request.data.xpath('/setJobs/job') sess_id = get_wialon_session_key(request.user) if jobs_els: for j in jobs_els: data = parse_xml_input_data(request, self.model_mapping, j) name = data.get('name') if not name: logout_session(request.user, sess_id) return error_response('Не указан параметр jobName', code='jobName_not_found') routes = get_routes(sess_id, with_points=True) units = get_units(sess_id) routes_ids = [x['id'] for x in routes] if data['route_id'] not in routes_ids: return error_response( 'Шаблон задания idRoute неверный или не принадлежит текущей организации', code='route_permission') units_cache = { u['id']: '%s (%s) [%s]' % (u['name'], u['number'], u['vin']) for u in units } try: data['unit_title'] = units_cache.get(int(data['unit_id'])) except (ValueError, TypeError, AttributeError): pass if not data['unit_title']: return error_response( 'Объект ID=%s не найден в текущем ресурсе организации' % data['unit_id'], code='unit_not_found_permission') routes_cache = {r['id']: r for r in routes} try: data['route_title'] = routes_cache.get( int(data['route_id']), {}).get('name') except (ValueError, TypeError, AttributeError): pass data['user'] = request.user self.job = self.model.objects.create(**data) register_job_notifications(self.job, sess_id, routes_cache=routes_cache) logout_session(request.user, sess_id) jobs.append(self.job) context = self.get_context_data(**kwargs) context.update({'now': utcnow(), 'acceptedJobs': jobs}) return XMLResponse('ura/ackjobs.xml', context)