saulsolis09 commited on
Commit
137aa75
·
1 Parent(s): 02114eb

Implemented IsFlagged column check

Browse files
Files changed (1) hide show
  1. app.py +28 -5
app.py CHANGED
@@ -56,7 +56,7 @@ FILTER_DOMINANT_COUNTY = False # process ALL counties (multi-county / full-stat
56
  # "csv" -> Master_Dataset.zip, every result bundled as a CSV (faster: no Excel
57
  # writing -- use this for very large / state-sized runs)
58
  # The individual per-category files are CSV in both modes.
59
- MASTER_OUTPUT = "csv"
60
 
61
  # How records are processed:
62
  # "stream" -> ONE COUNTY AT A TIME. The input is split into per-county temp
@@ -189,7 +189,7 @@ def _norm_fips(x):
189
  # values shaped like "05045-FAULKNER" (FIPS digits, a dash, a county name).
190
  # Header names are only used as a last-resort fallback.
191
  FIPS_COUNTY_PATTERN = r"^\s*\d{1,5}\s*-\s*[A-Za-z]"
192
- FALLBACK_FIPS_HEADERS = ["** REC FIPS-COUNTY NAME", "** REC FIPS-COUNTY", "County", "DocumentRecordingCountyFIPS"]
193
 
194
 
195
  def detect_fips_county_column(df, sample_size=1000, min_score=0.5):
@@ -258,6 +258,22 @@ def ensure_combined_county(df, fips_col, reason, wl, log=None):
258
  return "County", f"synthesized '<FIPS>-<NAME>' from bare FIPS column '{fips_col}'"
259
 
260
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  # =====================================================================
262
  # SELF-TEST (startup health check — same logic as the notebook's cell)
263
  # =====================================================================
@@ -657,6 +673,7 @@ def run_pipeline(uploaded_files, reference_file, blank_cities_not_in_list,
657
  del dfs
658
  gc.collect()
659
  _step(log, f"Merged shape: {df.shape}")
 
660
 
661
  # ---- Locate the FIPS-county column by CONTENT --------------------
662
  fips_col, fips_reason = detect_fips_county_column(df)
@@ -1046,6 +1063,7 @@ def process_county(cdf, wl, fips_col, cluster_offset,
1046
  Cluster_IDs are offset by `cluster_offset` so, processing counties in sorted
1047
  order, the numbering matches the whole-dataset ("memory") path."""
1048
  ignore = []
 
1049
  fips_col, _r = ensure_combined_county(cdf, fips_col, "", wl, None)
1050
  cdf, audit = fips_validate(cdf, blank_cities_not_in_list, ignore, wl=wl, fips_col=fips_col)
1051
 
@@ -1221,9 +1239,10 @@ def _split_by_county(uploaded_files, out_dir, log, chunksize=STREAM_CHUNK_ROWS):
1221
  else:
1222
  sample = pd.read_excel(first)
1223
  fips_col, reason = detect_fips_county_column(sample)
 
1224
  del sample
1225
  if fips_col is None:
1226
- return None, reason, []
1227
 
1228
  county_paths = {} # county label -> temp path
1229
  counter = [0]
@@ -1255,7 +1274,7 @@ def _split_by_county(uploaded_files, out_dir, log, chunksize=STREAM_CHUNK_ROWS):
1255
  _step(log, f"Split: routed {total:,} rows into {len(county_paths)} counties")
1256
 
1257
  ordered = sorted(county_paths.items(), key=lambda kv: str(kv[0]))
1258
- return fips_col, reason, ordered
1259
 
1260
 
1261
  def run_streaming(uploaded_files, reference_file, blank_cities_not_in_list,
@@ -1277,11 +1296,15 @@ def run_streaming(uploaded_files, reference_file, blank_cities_not_in_list,
1277
  return "\n".join(log) + f"\n\nCould not parse reference list: {e}", []
1278
 
1279
  _step(log, "Splitting input by county (streaming)...")
1280
- fips_col, reason, counties = _split_by_county(uploaded_files, out_dir, log)
1281
  if fips_col is None:
1282
  return ("\n".join(log) + "\n\nCOLUMN ERROR: could not find a FIPS-county column. "
1283
  "Expected values like '05045-FAULKNER'."), []
1284
  _step(log, f"FIPS-county column: '{fips_col}' ({reason}) | {len(counties)} counties")
 
 
 
 
1285
 
1286
  # combined output writers
1287
  audit_path = out_dir / "FIPS_Validation_Audit_ChangedRecords.csv"
 
56
  # "csv" -> Master_Dataset.zip, every result bundled as a CSV (faster: no Excel
57
  # writing -- use this for very large / state-sized runs)
58
  # The individual per-category files are CSV in both modes.
59
+ MASTER_OUTPUT = "excel"
60
 
61
  # How records are processed:
62
  # "stream" -> ONE COUNTY AT A TIME. The input is split into per-county temp
 
189
  # values shaped like "05045-FAULKNER" (FIPS digits, a dash, a county name).
190
  # Header names are only used as a last-resort fallback.
191
  FIPS_COUNTY_PATTERN = r"^\s*\d{1,5}\s*-\s*[A-Za-z]"
192
+ FALLBACK_FIPS_HEADERS = ["** REC FIPS-COUNTY NAME", "** REC FIPS-COUNTY", "County"]
193
 
194
 
195
  def detect_fips_county_column(df, sample_size=1000, min_score=0.5):
 
258
  return "County", f"synthesized '<FIPS>-<NAME>' from bare FIPS column '{fips_col}'"
259
 
260
 
261
+ def ensure_flag_columns(df, log=None):
262
+ """The Backoffice upload keys on RecordKey + IsFlagged + ComesFromMtg2, so the
263
+ final files must carry those flag columns. Data pulled straight from SQL lacks
264
+ IsFlagged / ComesFromMtg2 (the PBIX added them), so create them as FALSE when
265
+ missing. Columns already present (e.g. a PBIX pull) are left untouched."""
266
+ added = []
267
+ for col in ("IsFlagged", "ComesFromMtg2"):
268
+ if col not in df.columns:
269
+ df[col] = False
270
+ added.append(col)
271
+ if added and log is not None:
272
+ log.append(f"Added missing flag column(s) {', '.join(added)} = FALSE "
273
+ f"(not in input; required for the Backoffice upload).")
274
+ return df
275
+
276
+
277
  # =====================================================================
278
  # SELF-TEST (startup health check — same logic as the notebook's cell)
279
  # =====================================================================
 
673
  del dfs
674
  gc.collect()
675
  _step(log, f"Merged shape: {df.shape}")
676
+ ensure_flag_columns(df, log)
677
 
678
  # ---- Locate the FIPS-county column by CONTENT --------------------
679
  fips_col, fips_reason = detect_fips_county_column(df)
 
1063
  Cluster_IDs are offset by `cluster_offset` so, processing counties in sorted
1064
  order, the numbering matches the whole-dataset ("memory") path."""
1065
  ignore = []
1066
+ ensure_flag_columns(cdf, None)
1067
  fips_col, _r = ensure_combined_county(cdf, fips_col, "", wl, None)
1068
  cdf, audit = fips_validate(cdf, blank_cities_not_in_list, ignore, wl=wl, fips_col=fips_col)
1069
 
 
1239
  else:
1240
  sample = pd.read_excel(first)
1241
  fips_col, reason = detect_fips_county_column(sample)
1242
+ sample_cols = list(sample.columns)
1243
  del sample
1244
  if fips_col is None:
1245
+ return None, reason, [], sample_cols
1246
 
1247
  county_paths = {} # county label -> temp path
1248
  counter = [0]
 
1274
  _step(log, f"Split: routed {total:,} rows into {len(county_paths)} counties")
1275
 
1276
  ordered = sorted(county_paths.items(), key=lambda kv: str(kv[0]))
1277
+ return fips_col, reason, ordered, sample_cols
1278
 
1279
 
1280
  def run_streaming(uploaded_files, reference_file, blank_cities_not_in_list,
 
1296
  return "\n".join(log) + f"\n\nCould not parse reference list: {e}", []
1297
 
1298
  _step(log, "Splitting input by county (streaming)...")
1299
+ fips_col, reason, counties, sample_cols = _split_by_county(uploaded_files, out_dir, log)
1300
  if fips_col is None:
1301
  return ("\n".join(log) + "\n\nCOLUMN ERROR: could not find a FIPS-county column. "
1302
  "Expected values like '05045-FAULKNER'."), []
1303
  _step(log, f"FIPS-county column: '{fips_col}' ({reason}) | {len(counties)} counties")
1304
+ _missing_flags = [c for c in ("IsFlagged", "ComesFromMtg2") if c not in sample_cols]
1305
+ if _missing_flags:
1306
+ _step(log, f"Adding missing flag column(s) {', '.join(_missing_flags)} = FALSE "
1307
+ f"(required for the Backoffice upload)")
1308
 
1309
  # combined output writers
1310
  audit_path = out_dir / "FIPS_Validation_Audit_ChangedRecords.csv"