Mathias commited on
Commit
2bc6b2a
·
1 Parent(s): fe91a8b

Fix parser to handle DAILY sheet structure with activity rows

Browse files
Files changed (1) hide show
  1. app.py +100 -52
app.py CHANGED
@@ -47,69 +47,117 @@ def get_sheets_service():
47
 
48
  def parse_sheet_data(values):
49
  """
50
- Parse the raw sheet data into the format expected by the dashboard.
51
- Adjust this function based on your actual sheet structure.
 
 
 
 
 
 
 
 
 
 
 
52
  """
53
- if not values or len(values) < 2:
54
  return []
55
 
56
- # First row is headers
57
- headers = values[0]
58
- cases = []
59
 
60
- # Map column indices (adjust based on your sheet structure)
61
- # Expected columns: Case, GS, Week2_SQL, Week2_SQLTarget, Week2_Calls, Week2_CallsTarget, etc.
62
- col_map = {}
63
- for i, h in enumerate(headers):
64
- col_map[h.lower().strip()] = i
65
 
66
- for row_idx, row in enumerate(values[1:], start=2):
67
- if not row or len(row) < 2:
 
 
68
  continue
69
 
70
- try:
71
- # Get basic info
72
- case_name = row[col_map.get("case", 0)] if col_map.get("case", 0) < len(row) else ""
73
- gs_name = row[col_map.get("gs", 1)] if col_map.get("gs", 1) < len(row) else ""
74
-
75
- if not case_name or not gs_name:
76
- continue
77
-
78
- # Build weeks data
79
- weeks = {}
80
- for week_num in [2, 3, 4, 5]:
81
- week_key = f"w{week_num}"
82
- weeks[week_num] = {
83
- "sql": safe_int(row, col_map.get(f"{week_key}_sql")),
84
- "sqlTarget": safe_int(row, col_map.get(f"{week_key}_sqltarget")),
85
- "calls": safe_int(row, col_map.get(f"{week_key}_calls")),
86
- "callsTarget": safe_int(row, col_map.get(f"{week_key}_callstarget")),
87
- "emails": safe_int(row, col_map.get(f"{week_key}_emails")),
88
- "emailsTarget": safe_int(row, col_map.get(f"{week_key}_emailstarget")),
89
- "linkedin": safe_int(row, col_map.get(f"{week_key}_linkedin")),
90
- "linkedinTarget": safe_int(row, col_map.get(f"{week_key}_linkedintarget")),
91
- }
92
-
93
- # Monthly totals
94
- monthly_total = {
95
- "sql": safe_int(row, col_map.get("monthly_sql")),
96
- "sqlTarget": safe_int(row, col_map.get("monthly_sqltarget")),
97
- "activity": safe_int(row, col_map.get("monthly_activity")),
98
- "activityTarget": safe_int(row, col_map.get("monthly_activitytarget")),
99
- }
100
 
101
- cases.append({
102
- "id": row_idx,
103
- "case": case_name,
104
- "gs": gs_name,
105
- "weeks": weeks,
106
- "monthlyTotal": monthly_total
107
- })
108
 
109
- except Exception as e:
110
- print(f"Error parsing row {row_idx}: {e}")
111
  continue
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  return cases
114
 
115
 
 
47
 
48
  def parse_sheet_data(values):
49
  """
50
+ Parse the DAILY sheet data into the format expected by the dashboard.
51
+
52
+ DAILY sheet structure:
53
+ - Column A: Case name (may be empty for continuation rows)
54
+ - Column B: GS/SDR name (may be empty for continuation rows)
55
+ - Column C: Activity type (Calls, Emails, LinkedIn, Prospects, Discovery, SQL)
56
+ - Columns D-H: Week 2 daily data (M, T, W, T, F)
57
+ - Column I: Week 2 total
58
+ - Column J: Week 2 percentage
59
+ - Columns K-O: Week 3 daily data
60
+ - Column P: Week 3 total
61
+ - Column Q: Week 3 percentage
62
+ - And so on for Week 4, Week 5...
63
  """
64
+ if not values or len(values) < 5:
65
  return []
66
 
67
+ # Find week columns by looking at header rows
68
+ # Row 1 has week labels, Row 4 has day labels (M, T, W, T, F)
69
+ # Data starts from row 5
70
 
71
+ # Build a map of case+gs -> activity data
72
+ case_data = {}
73
+ current_case = None
74
+ current_gs = None
 
75
 
76
+ for row_idx, row in enumerate(values):
77
+ if row_idx < 4: # Skip header rows
78
+ continue
79
+ if not row or len(row) < 3:
80
  continue
81
 
82
+ # Column A: Case, Column B: GS, Column C: Activity
83
+ case_name = row[0].strip() if len(row) > 0 and row[0] else None
84
+ gs_name = row[1].strip() if len(row) > 1 and row[1] else None
85
+ activity = row[2].strip() if len(row) > 2 and row[2] else None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
87
+ # Update current case/gs if provided
88
+ if case_name:
89
+ current_case = case_name
90
+ if gs_name:
91
+ current_gs = gs_name
 
 
92
 
93
+ if not current_case or not current_gs or not activity:
 
94
  continue
95
 
96
+ # Create key for this case+gs combination
97
+ key = f"{current_case}|{current_gs}"
98
+
99
+ if key not in case_data:
100
+ case_data[key] = {
101
+ "case": current_case,
102
+ "gs": current_gs,
103
+ "weeks": {2: {}, 3: {}, 4: {}, 5: {}},
104
+ "monthlyTotal": {"sql": 0, "sqlTarget": 0, "activity": 0, "activityTarget": 0}
105
+ }
106
+
107
+ # Map activity types to our data structure
108
+ activity_lower = activity.lower()
109
+ activity_map = {
110
+ "calls": "calls",
111
+ "emails": "emails",
112
+ "linkedin": "linkedin",
113
+ "prospects": "prospects",
114
+ "prospects (activated)": "prospects",
115
+ "discovery": "discovery",
116
+ "sql": "sql"
117
+ }
118
+
119
+ activity_key = activity_map.get(activity_lower)
120
+ if not activity_key:
121
+ continue
122
+
123
+ # Week column positions (0-indexed):
124
+ # Week 2: D-H (3-7) daily, I (8) total
125
+ # Week 3: K-O (10-14) daily, P (15) total
126
+ # Week 4: R-V (17-21) daily, W (22) total
127
+ # Week 5: Y-AC (24-28) daily, AD (29) total
128
+ week_configs = [
129
+ (2, 8), # Week 2 total in column I (index 8)
130
+ (3, 15), # Week 3 total in column P (index 15)
131
+ (4, 22), # Week 4 total in column W (index 22)
132
+ (5, 29), # Week 5 total in column AD (index 29)
133
+ ]
134
+
135
+ for week_num, total_col in week_configs:
136
+ total_val = safe_int(row, total_col)
137
+ if week_num not in case_data[key]["weeks"]:
138
+ case_data[key]["weeks"][week_num] = {}
139
+ case_data[key]["weeks"][week_num][activity_key] = total_val
140
+ case_data[key]["weeks"][week_num][f"{activity_key}Target"] = 0 # Targets not in this sheet
141
+
142
+ # Add to monthly total
143
+ if activity_key == "sql":
144
+ for week_num, total_col in week_configs:
145
+ case_data[key]["monthlyTotal"]["sql"] += safe_int(row, total_col)
146
+ elif activity_key in ["calls", "emails", "linkedin", "prospects"]:
147
+ for week_num, total_col in week_configs:
148
+ case_data[key]["monthlyTotal"]["activity"] += safe_int(row, total_col)
149
+
150
+ # Convert to list format
151
+ cases = []
152
+ for idx, (key, data) in enumerate(case_data.items()):
153
+ cases.append({
154
+ "id": idx + 1,
155
+ "case": data["case"],
156
+ "gs": data["gs"],
157
+ "weeks": data["weeks"],
158
+ "monthlyTotal": data["monthlyTotal"]
159
+ })
160
+
161
  return cases
162
 
163