""" Interactive setup wizard for configuring the sales analysis template Asks clarifying questions to configure config.py for your specific company and data """ import os import sys from pathlib import Path def print_header(text): """Print a formatted header""" print("\n" + "="*70) print(f" {text}") print("="*70 + "\n") def ask_question(prompt, default=None, validator=None): """ Ask a question and return the answer Args: prompt: Question to ask default: Default value if user just presses Enter validator: Optional function to validate input Returns: User's answer (or default) """ if default: full_prompt = f"{prompt} [{default}]: " else: full_prompt = f"{prompt}: " while True: answer = input(full_prompt).strip() if not answer and default: return default elif not answer: print(" Please provide an answer.") continue if validator: try: return validator(answer) except Exception as e: print(f" Invalid input: {e}") continue return answer def validate_yes_no(answer): """Validate yes/no answer""" answer_lower = answer.lower() if answer_lower in ['y', 'yes', 'true', '1']: return True elif answer_lower in ['n', 'no', 'false', '0']: return False else: raise ValueError("Please answer 'yes' or 'no'") def validate_int(answer): """Validate integer answer""" return int(answer) def validate_file_exists(answer): """Validate that file exists""" if not Path(answer).exists(): raise ValueError(f"File not found: {answer}") return answer def main(): """Run the setup wizard""" print_header("Sales Analysis Template - Setup Wizard") print("This wizard will help you configure the template for your company's data.") print("You can press Enter to accept defaults (shown in brackets).\n") responses = {} # Company Information print_header("Company Information") responses['company_name'] = ask_question("Company Name", default="Your Company Name") responses['analysis_date'] = ask_question("Analysis Date (YYYY-MM-DD)", default="2026-01-12") # Data File print_header("Data File Configuration") print("Where is your sales data CSV file located?") data_file = ask_question("Data file name (e.g., sales_data.csv)", default="sales_data.csv") # Check if file exists if Path(data_file).exists(): print(f" ✓ Found: {data_file}") else: print(f" ⚠ Warning: {data_file} not found. Make sure to place it in the template directory.") responses['data_file'] = data_file # Column Mapping print_header("Column Mapping") print("What are the column names in your CSV file?") print("(Press Enter to accept defaults if your columns match common names)\n") responses['revenue_column'] = ask_question("Revenue/Amount column name", default="USD") responses['date_column'] = ask_question("Primary date column name", default="InvoiceDate") has_fallback = ask_question("Do you have fallback date columns (Month, Year)?", default="yes", validator=validate_yes_no) if has_fallback: fallback_str = ask_question("Fallback date columns (comma-separated)", default="Month, Year") responses['date_fallback'] = [col.strip() for col in fallback_str.split(',')] else: responses['date_fallback'] = [] responses['customer_column'] = ask_question("Customer/Account column name", default="Customer") responses['item_column'] = ask_question("Item/Product column name", default="Item") has_quantity = ask_question("Do you have a Quantity column?", default="yes", validator=validate_yes_no) if has_quantity: responses['quantity_column'] = ask_question("Quantity column name", default="Quantity") else: responses['quantity_column'] = None # Date Range print_header("Date Range Configuration") responses['min_year'] = ask_question("Minimum year to include in analysis", default="2021", validator=validate_int) responses['max_date'] = ask_question("Maximum date (YYYY-MM-DD)", default="2025-09-30") years_str = ask_question("Analysis years (comma-separated, e.g., 2021,2022,2023,2024,2025)", default="2021,2022,2023,2024,2025") responses['analysis_years'] = [int(y.strip()) for y in years_str.split(',')] # LTM Configuration print_header("LTM (Last Twelve Months) Configuration") print("LTM is used for the most recent partial year to enable apples-to-apples comparison.") print("Example: If your latest data is through September 2025, use Oct 2024 - Sep 2025.\n") use_ltm = ask_question("Do you need LTM for the most recent year?", default="yes", validator=validate_yes_no) responses['ltm_enabled'] = use_ltm if use_ltm: responses['ltm_start_month'] = ask_question("LTM start month (1-12)", default="10", validator=validate_int) responses['ltm_start_year'] = ask_question("LTM start year", default="2024", validator=validate_int) responses['ltm_end_month'] = ask_question("LTM end month (1-12)", default="9", validator=validate_int) responses['ltm_end_year'] = ask_question("LTM end year", default="2025", validator=validate_int) else: responses['ltm_start_month'] = 10 responses['ltm_start_year'] = 2024 responses['ltm_end_month'] = 9 responses['ltm_end_year'] = 2025 # Exclusion Filters print_header("Exclusion Filters (Optional)") use_exclusions = ask_question("Do you need to exclude specific segments (e.g., test accounts, business units)?", default="no", validator=validate_yes_no) responses['exclusions_enabled'] = use_exclusions if use_exclusions: responses['exclude_column'] = ask_question("Column name to filter on", default="Country") exclude_values_str = ask_question("Values to exclude (comma-separated)", default="") responses['exclude_values'] = [v.strip() for v in exclude_values_str.split(',') if v.strip()] else: responses['exclude_column'] = None responses['exclude_values'] = [] # Generate config.py print_header("Generating Configuration") print("Updating config.py with your settings...") # Read current config.py config_path = Path('config.py') if not config_path.exists(): print("ERROR: config.py not found!") return with open(config_path, 'r', encoding='utf-8') as f: config_content = f.read() # Replace values replacements = { "COMPANY_NAME = \"Your Company Name\"": f"COMPANY_NAME = \"{responses['company_name']}\"", "ANALYSIS_DATE = \"2026-01-12\"": f"ANALYSIS_DATE = \"{responses['analysis_date']}\"", "DATA_FILE = 'sales_data.csv'": f"DATA_FILE = '{responses['data_file']}'", "REVENUE_COLUMN = 'USD'": f"REVENUE_COLUMN = '{responses['revenue_column']}'", "DATE_COLUMN = 'InvoiceDate'": f"DATE_COLUMN = '{responses['date_column']}'", "DATE_FALLBACK_COLUMNS = ['Month', 'Year']": f"DATE_FALLBACK_COLUMNS = {responses['date_fallback']}", "CUSTOMER_COLUMN = 'Customer'": f"CUSTOMER_COLUMN = '{responses['customer_column']}'", "ITEM_COLUMN = 'Item'": f"ITEM_COLUMN = '{responses['item_column']}'", "QUANTITY_COLUMN = 'Quantity'": f"QUANTITY_COLUMN = '{responses['quantity_column']}'" if responses['quantity_column'] else "QUANTITY_COLUMN = None", "MIN_YEAR = 2021": f"MIN_YEAR = {responses['min_year']}", "MAX_DATE = pd.Timestamp('2025-09-30')": f"MAX_DATE = pd.Timestamp('{responses['max_date']}')", "ANALYSIS_YEARS = [2021, 2022, 2023, 2024, 2025]": f"ANALYSIS_YEARS = {responses['analysis_years']}", "LTM_ENABLED = True": f"LTM_ENABLED = {responses['ltm_enabled']}", "LTM_START_MONTH = 10": f"LTM_START_MONTH = {responses['ltm_start_month']}", "LTM_START_YEAR = 2024": f"LTM_START_YEAR = {responses['ltm_start_year']}", "LTM_END_MONTH = 9": f"LTM_END_MONTH = {responses['ltm_end_month']}", "LTM_END_YEAR = 2025": f"LTM_END_YEAR = {responses['ltm_end_year']}", } # Handle exclusions if responses['exclusions_enabled']: exclusions_config = f"""EXCLUSION_FILTERS = {{ 'enabled': True, 'exclude_by_column': '{responses['exclude_column']}', 'exclude_values': {responses['exclude_values']} }}""" # Replace the exclusion filters section import re pattern = r"EXCLUSION_FILTERS = \{.*?\}" config_content = re.sub(pattern, exclusions_config, config_content, flags=re.DOTALL) else: exclusions_config = """EXCLUSION_FILTERS = { 'enabled': False, 'exclude_by_column': None, 'exclude_values': [] }""" import re pattern = r"EXCLUSION_FILTERS = \{.*?\}" config_content = re.sub(pattern, exclusions_config, config_content, flags=re.DOTALL) # Apply replacements for old, new in replacements.items(): if old in config_content: config_content = config_content.replace(old, new) # Write updated config with open(config_path, 'w', encoding='utf-8') as f: f.write(config_content) print(" ✓ Configuration updated successfully!") # Summary print_header("Setup Complete") print("Your configuration has been saved to config.py") print("\nNext steps:") print("1. Place your data file in the template directory (if not already there)") print("2. Test data loading: python -c \"from data_loader import load_sales_data; from config import get_data_path; df = load_sales_data(get_data_path()); print(f'Loaded {len(df):,} rows')\"") print("3. Review config.py and adjust any settings as needed") print("4. Start creating your analysis scripts using analysis_template.py") print("\nFor help, see README.md") if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\n\nSetup cancelled by user.") sys.exit(0)