import json import logging from datetime import datetime, timedelta from flask import request, jsonify from dateutil import parser, tz from routes import app logger = logging.getLogger(__name__) def get_next_working_time(dt, work_start_hour, work_end_hour): while True: if dt.weekday() >= 5: # Weekend, move to next working day dt += timedelta(days=1) dt = dt.replace(hour=work_start_hour, minute=0, second=0, microsecond=0) else: work_start = dt.replace(hour=work_start_hour, minute=0, second=0, microsecond=0) work_end = dt.replace(hour=work_end_hour, minute=0, second=0, microsecond=0) if dt < work_start: return work_start elif dt >= work_end: # After working hours, move to next day dt += timedelta(days=1) dt = dt.replace(hour=work_start_hour, minute=0, second=0, microsecond=0) else: # During working hours return dt def compute_working_seconds(start_dt, end_dt, work_start_hour, work_end_hour): if start_dt >= end_dt: return 0 total_seconds = 0 current_dt = start_dt while current_dt < end_dt: if current_dt.weekday() >= 5: # Weekend, move to next working day current_dt += timedelta(days=1) current_dt = current_dt.replace(hour=work_start_hour, minute=0, second=0, microsecond=0) continue work_start = current_dt.replace(hour=work_start_hour, minute=0, second=0, microsecond=0) work_end = current_dt.replace(hour=work_end_hour, minute=0, second=0, microsecond=0) if current_dt < work_start: current_dt = work_start if current_dt >= work_end: # Move to next working day current_dt += timedelta(days=1) continue period_end = min(work_end, end_dt) total_seconds += (period_end - current_dt).total_seconds() current_dt = period_end return total_seconds def get_base_subject(subject): while subject.startswith("RE: "): subject = subject[4:] return subject @app.route('/mailtime', methods=['POST']) def mail_time(): data = request.get_json() logging.info("Data received for evaluation: {}".format(data)) users = {} for user in data.get("users", []): name = user["name"] office_hours = user["officeHours"] users[name] = { "name": name, "timezone": office_hours["timeZone"], "start_hour": office_hours["start"], "end_hour": office_hours["end"], "response_times": [] } # Build threads based on base subjects threads = {} for email in data.get("emails", []): subject = email["subject"] base_subject = get_base_subject(subject) if base_subject not in threads: threads[base_subject] = [] email['parsed_time'] = parser.isoparse(email['timeSent']) threads[base_subject].append(email) # Process emails in threads for thread_emails in threads.values(): # Sort emails by parsed_time thread_emails.sort(key=lambda e: e['parsed_time']) for i in range(1, len(thread_emails)): current_email = thread_emails[i] previous_email = thread_emails[i - 1] sender = current_email['sender'] sender_info = users[sender] sender_tz = tz.gettz(sender_info['timezone']) # Time when sender received the previous email, in sender's timezone previous_email_time = previous_email['parsed_time'].astimezone(sender_tz) # Time when sender sent the reply, in sender's timezone current_email_time = current_email['parsed_time'].astimezone(sender_tz) work_start_hour = sender_info['start_hour'] work_end_hour = sender_info['end_hour'] # Adjusted start time: when sender could start responding adjusted_start_time = get_next_working_time(previous_email_time, work_start_hour, work_end_hour) # Compute working seconds between adjusted_start_time and current_email_time working_seconds = compute_working_seconds(adjusted_start_time, current_email_time, work_start_hour, work_end_hour) sender_info['response_times'].append(working_seconds) # Compute average response times result = {} for user_name, user_info in users.items(): response_times = user_info['response_times'] if response_times: avg_response_time = sum(response_times) / len(response_times) else: avg_response_time = 0 avg_response_time = int(round(avg_response_time)) result[user_name] = avg_response_time logging.info("Computed result: {}".format(result)) return jsonify(result)