91 lines
5.0 KiB
Python
91 lines
5.0 KiB
Python
|
||
import os
|
||
import json
|
||
import logging
|
||
from typing import List, Dict
|
||
from datetime import datetime, timedelta
|
||
from dateutil import parser
|
||
|
||
log = logging.getLogger(__name__)
|
||
|
||
def process_json_files(directory: str) -> List[Dict]:
|
||
"""
|
||
Сканирует директорию, читает все .json файлы и извлекает из них данные
|
||
о фискальных регистраторах в стандартизированном формате.
|
||
Файлы, старше 21 дня (по полю 'current_time'), игнорируются.
|
||
|
||
:param directory: Путь к директории с JSON файлами.
|
||
:return: Список словарей, где каждый словарь представляет один ФР.
|
||
"""
|
||
if not os.path.isdir(directory):
|
||
log.error(f"Указанный путь не является директорией: {directory}")
|
||
return []
|
||
|
||
all_fr_data = []
|
||
log.info(f"Начинаю обработку JSON файлов из директории: {directory}")
|
||
|
||
# Пороговая дата: всё что старше, считаем неактуальным
|
||
freshness_threshold = datetime.now() - timedelta(days=21)
|
||
|
||
for filename in os.listdir(directory):
|
||
if filename.lower().endswith('.json'):
|
||
file_path = os.path.join(directory, filename)
|
||
try:
|
||
with open(file_path, 'r', encoding='utf-8') as f:
|
||
data = json.load(f)
|
||
|
||
current_time_str = data.get('current_time')
|
||
if not current_time_str:
|
||
log.warning(f"Пропущен файл {filename}: отсутствует поле 'current_time' для проверки актуальности.")
|
||
continue
|
||
|
||
try:
|
||
file_datetime = parser.parse(current_time_str)
|
||
# Приводим к aware-объекту с локальной таймзоной, если он naive, для корректного сравнения
|
||
if file_datetime.tzinfo is None:
|
||
file_datetime = file_datetime.astimezone()
|
||
|
||
# Сравниваем с пороговым значением (пороговое значение тоже делаем aware)
|
||
if file_datetime < freshness_threshold.astimezone(file_datetime.tzinfo):
|
||
log.warning(f"Пропущен файл {filename}: данные неактуальны (старше 21 дня). "
|
||
f"Дата файла: {file_datetime.strftime('%Y-%m-%d')}")
|
||
continue
|
||
except parser.ParserError:
|
||
log.error(f"Не удалось распознать дату в поле 'current_time' в файле {filename}: '{current_time_str}'")
|
||
continue
|
||
|
||
if 'serialNumber' not in data or not data['serialNumber']:
|
||
log.warning(f"Пропущен файл {filename}: отсутствует serialNumber.")
|
||
continue
|
||
|
||
# Поля teamviewer_id могут быть написаны по-разному,
|
||
# например teamviever_id. Обработаем это.
|
||
teamviewer_id = data.get('teamviewer_id') or data.get('teamviever_id')
|
||
|
||
fr_record = {
|
||
'serialNumber': data.get('serialNumber'),
|
||
'modelName': data.get('modelName'),
|
||
'RNM': data.get('RNM') or '0000000000000000',
|
||
'organizationName': data.get('organizationName'),
|
||
'fn_serial': data.get('fn_serial') or '0000000000000000',
|
||
'datetime_reg': data.get('datetime_reg'),
|
||
'dateTime_end': data.get('dateTime_end'),
|
||
'ofdName': data.get('ofdName'),
|
||
'bootVersion': data.get('bootVersion'),
|
||
'ffdVersion': data.get('ffdVersion'), # В примере '120', а не '1.2'. Нужно будет уточнить.
|
||
'fnExecution': data.get('fnExecution'),
|
||
'INN': data.get('INN'),
|
||
'anydesk_id': data.get('anydesk_id'), # Приходят чистые
|
||
'teamviewer_id': teamviewer_id, # Приходят чистые
|
||
'lastModifiedDate': data.get('current_time')
|
||
}
|
||
all_fr_data.append(fr_record)
|
||
log.debug(f"Успешно обработан файл {filename}. S/N: {fr_record['serialNumber']}")
|
||
|
||
except json.JSONDecodeError:
|
||
log.error(f"Ошибка декодирования JSON в файле: {filename}")
|
||
except Exception as e:
|
||
log.error(f"Неизвестная ошибка при обработке файла {filename}: {e}")
|
||
|
||
log.info(f"Обработка JSON файлов завершена. Получено {len(all_fr_data)} записей.")
|
||
return all_fr_data |