Adding CLI parameters : --add-suffix and --exclude-drafts

This commit is contained in:
2026-05-07 00:19:58 +01:00
parent 123e9d3338
commit ad0ebb307d
4 changed files with 73 additions and 29 deletions

View File

@@ -88,6 +88,8 @@ from eb_dashboard_utils import (
get_config_path,
set_dashboard_config_path_override,
get_dashboard_config_path,
set_output_file_suffix,
get_output_filename,
thread_local_storage,
run_with_context
)
@@ -105,8 +107,23 @@ from eb_dashboard_excel_export import (
set_dependencies as excel_set_dependencies
)
logging.basicConfig(level=logging.WARNING, format='%(asctime)s - %(levelname)s - %(message)s', filename=LOG_FILE_NAME,
filemode='w')
def _fatal_cli_error(message):
"""Print a CLI error then wait for Enter before exiting (keeps console open on Windows Explorer launch)."""
print(message)
input("Press Enter to exit...")
sys.exit(1)
# Handle --add-suffix <value> early: must precede logging.basicConfig (affects log filename)
if "--add-suffix" in sys.argv:
_idx = sys.argv.index("--add-suffix")
if _idx + 1 >= len(sys.argv):
_fatal_cli_error("Error: --add-suffix requires a value")
set_output_file_suffix(sys.argv[_idx + 1])
del sys.argv[_idx:_idx + 2]
logging.basicConfig(level=logging.WARNING, format='%(asctime)s - %(levelname)s - %(message)s',
filename=get_output_filename(LOG_FILE_NAME), filemode='w')
# ============================================================================
@@ -132,6 +149,7 @@ _user_interaction_lock = threading.Lock()
# Global variables (mutable, set at runtime - not constants)
inclusions_mapping_config = []
organizations_mapping_config = []
_exclude_drafts = False # Set by --exclude-drafts CLI arg if provided
excel_export_config = None
excel_export_enabled = False
@@ -158,8 +176,7 @@ if "--debug" in sys.argv:
if "--config" in sys.argv:
_idx = sys.argv.index("--config")
if _idx + 1 >= len(sys.argv):
print("Error: --config requires a file path argument")
sys.exit(1)
_fatal_cli_error("Error: --config requires a file path argument")
_raw_config_path = sys.argv[_idx + 1]
del sys.argv[_idx:_idx + 2]
if os.path.isabs(_raw_config_path):
@@ -167,6 +184,11 @@ if "--config" in sys.argv:
else:
set_dashboard_config_path_override(os.path.join(get_config_path(), _raw_config_path))
# Handle --exclude-drafts flag (remove from sys.argv to preserve positional args)
_exclude_drafts = "--exclude-drafts" in sys.argv
if _exclude_drafts:
sys.argv.remove("--exclude-drafts")
# --- Progress Bar Configuration ---
# NOTE: BAR_N_FMT_WIDTH, BAR_TOTAL_FMT_WIDTH, BAR_TIME_WIDTH, BAR_RATE_WIDTH
# are imported from eb_dashboard_constants.py (SINGLE SOURCE OF TRUTH)
@@ -1233,14 +1255,14 @@ def get_all_questionnaires_by_patient(patient_id, record_data):
q_category = get_nested_value(item, path=["questionnaire", "category"])
answers = get_nested_value(item, path=["answers"], default={})
# ── UNLINKED PATIENT FILTER ─────────────────────────────────────────────
# If answers.patient is missing, null, or does not match the requested
# patient_id, the questionnaire is considered unlinked → clear answers
# to prevent use of orphaned data.
# (disable: comment out the block below)
#answers_patient = answers.get("subject") if isinstance(answers, dict) else None
#if not answers_patient or answers_patient != patient_id:
# answers = {}
# ── DRAFT ANSWERS FILTER ────────────────────────────────────────────────
# "Draft" answers have a missing or mismatched subject (patient id):
# they are not yet submitted and should not be treated as valid patient data.
# Activated via --exclude-drafts CLI flag.
if _exclude_drafts:
answers_patient = answers.get("subject") if isinstance(answers, dict) else None
if not answers_patient or answers_patient != patient_id:
answers = {}
# ────────────────────────────────────────────────────────────────────────
if q_id:
@@ -1497,7 +1519,7 @@ def main():
load_organizations_mapping_config()
# Completely externalized Excel-only workflow
export_excel_only(sys.argv, INCLUSIONS_FILE_NAME, ORGANIZATIONS_FILE_NAME,
export_excel_only(sys.argv, get_output_filename(INCLUSIONS_FILE_NAME), get_output_filename(ORGANIZATIONS_FILE_NAME),
inclusions_mapping_config, organizations_mapping_config)
return
@@ -1642,7 +1664,7 @@ def main():
has_coherence_critical, has_regression_critical = run_quality_checks(
current_inclusions=output_inclusions, # list: données en mémoire (nouvellement collectées)
organizations_list=organizations_list, # list: données en mémoire avec compteurs
old_inclusions_filename=INCLUSIONS_FILE_NAME # str: "endobest_inclusions.json" (version courante sur disque)
old_inclusions_filename=get_output_filename(INCLUSIONS_FILE_NAME) # str: current file on disk (with suffix if any)
)
# === CHECK FOR CRITICAL ISSUES AND ASK USER CONFIRMATION ===
@@ -1667,9 +1689,9 @@ def main():
# === WRITE NEW FILES ===
print("Writing files...")
with open(INCLUSIONS_FILE_NAME, 'w', encoding='utf-8') as f_json:
with open(get_output_filename(INCLUSIONS_FILE_NAME), 'w', encoding='utf-8') as f_json:
json.dump(output_inclusions, f_json, indent=4, ensure_ascii=False)
with open(ORGANIZATIONS_FILE_NAME, 'w', encoding='utf-8') as f_json:
with open(get_output_filename(ORGANIZATIONS_FILE_NAME), 'w', encoding='utf-8') as f_json:
json.dump(organizations_list, f_json, indent=4, ensure_ascii=False)
console.print("[green]✓ Data saved to JSON files[/green]")