Auto-update: Mon Oct 28 12:40:45 PDT 2024
This commit is contained in:
parent
f7f6e3e30e
commit
7ac4de503f
1 changed files with 38 additions and 11 deletions
|
@ -659,8 +659,20 @@ async def process_att_csv(
|
||||||
"""Process AT&T CSV file and post phone calls to Timing."""
|
"""Process AT&T CSV file and post phone calls to Timing."""
|
||||||
|
|
||||||
# Load the phone lookup data from file
|
# Load the phone lookup data from file
|
||||||
cleaned_lookup = load_phone_lookup()
|
try:
|
||||||
|
with open(PHONE_LOOKUP_PATH, 'r') as f:
|
||||||
|
phone_lookup = json.load(f)
|
||||||
|
cleaned_lookup = {
|
||||||
|
clean_phone_number(phone): name
|
||||||
|
for phone, name in phone_lookup.items()
|
||||||
|
}
|
||||||
|
except FileNotFoundError:
|
||||||
|
l.warning(f"Phone lookup file not found at {PHONE_LOOKUP_PATH}")
|
||||||
|
cleaned_lookup = {}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
l.error(f"Invalid JSON in phone lookup file at {PHONE_LOOKUP_PATH}")
|
||||||
|
cleaned_lookup = {}
|
||||||
|
|
||||||
# Read and process the CSV
|
# Read and process the CSV
|
||||||
content = await file.read()
|
content = await file.read()
|
||||||
content = content.decode('utf-8')
|
content = content.decode('utf-8')
|
||||||
|
@ -682,6 +694,9 @@ async def process_att_csv(
|
||||||
csv_reader = csv.DictReader(lines[start_index:])
|
csv_reader = csv.DictReader(lines[start_index:])
|
||||||
|
|
||||||
entries = []
|
entries = []
|
||||||
|
successes = 0
|
||||||
|
failures = 0
|
||||||
|
|
||||||
for row in csv_reader:
|
for row in csv_reader:
|
||||||
if not row.get('Contact'): # Skip empty rows
|
if not row.get('Contact'): # Skip empty rows
|
||||||
continue
|
continue
|
||||||
|
@ -697,8 +712,10 @@ async def process_att_csv(
|
||||||
time_str = row['Time'].strip()
|
time_str = row['Time'].strip()
|
||||||
try:
|
try:
|
||||||
dt = datetime.strptime(f"{date_str} {time_str}", "%b %d, %Y %I:%M %p")
|
dt = datetime.strptime(f"{date_str} {time_str}", "%b %d, %Y %I:%M %p")
|
||||||
|
dt = pacific.localize(dt) # Make timezone-aware
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
l.warning(f"Failed to parse date/time: {date_str} {time_str}")
|
l.warning(f"Failed to parse date/time: {date_str} {time_str}")
|
||||||
|
failures += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Calculate end time based on minutes
|
# Calculate end time based on minutes
|
||||||
|
@ -707,34 +724,44 @@ async def process_att_csv(
|
||||||
end_dt = dt + timedelta(minutes=minutes)
|
end_dt = dt + timedelta(minutes=minutes)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
l.warning(f"Invalid minutes value: {row['Minutes']}")
|
l.warning(f"Invalid minutes value: {row['Minutes']}")
|
||||||
|
failures += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Create the time entry
|
# Create the time entry
|
||||||
entry = {
|
entry = {
|
||||||
"start_date": dt.strftime("%Y-%m-%dT%H:%M:%S-07:00"),
|
"start_date": dt.isoformat(),
|
||||||
"end_date": end_dt.strftime("%Y-%m-%dT%H:%M:%S-07:00"),
|
"end_date": end_dt.isoformat(),
|
||||||
"project": "📞 Phone Calls",
|
"project": "📞 Phone Calls",
|
||||||
"title": f"{row['Incoming/Outgoing']} - {contact_name}",
|
"title": f"{row['Incoming/Outgoing']} - {contact_name}",
|
||||||
"notes": f"Call via {row['Type']} from {row['Location']}",
|
"notes": f"Call via {row['Type']} from {row['Location']}",
|
||||||
"replace_existing": False
|
"replace_existing": False
|
||||||
}
|
}
|
||||||
|
|
||||||
# Post to Timing API
|
|
||||||
try:
|
try:
|
||||||
status, response = await post_time_entry_to_timing(entry)
|
await post_time_entry_to_timing(entry)
|
||||||
if status != 200:
|
entries.append(entry)
|
||||||
l.warning(f"Failed to post entry: {response}")
|
successes += 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
l.error(f"Error posting entry: {e}")
|
l.error(f"Error posting entry: {e}")
|
||||||
|
failures += 1
|
||||||
entries.append(entry)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"message": f"Processed {len(entries)} phone calls",
|
"message": f"Processed {len(entries)} phone calls ({successes} successes, {failures} failures)",
|
||||||
"entries": entries,
|
"entries": entries,
|
||||||
"lookup_matches": sum(1 for e in entries if e['title'].split(' - ')[1] in cleaned_lookup.values())
|
"lookup_matches": sum(1 for e in entries if e['title'].split(' - ')[1] in cleaned_lookup.values())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def clean_phone_number(phone: str) -> str:
|
||||||
|
"""Clean phone number by removing special characters and handling country code."""
|
||||||
|
# Remove all special characters
|
||||||
|
cleaned = re.sub(r'[\(\)\s\+\-\.]', '', phone)
|
||||||
|
|
||||||
|
# Handle 11-digit numbers starting with 1
|
||||||
|
if len(cleaned) == 11 and cleaned.startswith('1'):
|
||||||
|
cleaned = cleaned[1:]
|
||||||
|
|
||||||
|
return cleaned
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@timing.get("/time/flagemoji/{country_code}")
|
@timing.get("/time/flagemoji/{country_code}")
|
||||||
|
|
Loading…
Reference in a new issue