diff --git a/demo-03/employee_data_processor.py b/demo-03/employee_data_processor.py new file mode 100644 index 0000000..4755429 --- /dev/null +++ b/demo-03/employee_data_processor.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python3 +import csv +import json +import datetime +import re + +processed_records = [] +skipped_records = [] +total_salary = 0 +dept_count = {} + +def process_employee_data(): + global processed_records, skipped_records, total_salary, dept_count + file_path = "employees.csv" + json_output_path = "report.json" + html_output_path = "report.html" + + try: + with open(file_path, 'r') as f: + reader = csv.DictReader(f) + rows = list(reader) + + print(f"Reading file: {file_path}") + print(f"Total rows in CSV: {len(rows)}") + + for row in rows: + name = row['name'] + email = row['email'] + dept = row['department'] + salary = row['salary'] + hire_date = row['hire_date'] + + # Validation part 1 - email + if not email or '@' not in email or '.' not in email.split('@')[1]: + print(f"WARNING: Invalid email for {name}: {email}") + skipped_records.append({'name': name, 'reason': 'Invalid email'}) + continue + + # Validation part 2 - salary + try: + sal = int(salary) + except: + print(f"WARNING: Invalid salary for {name}: {salary}") + skipped_records.append({'name': name, 'reason': 'Invalid salary'}) + continue + + if sal < 0: + print(f"WARNING: Negative salary for {name}: {sal}") + skipped_records.append({'name': name, 'reason': 'Negative salary'}) + continue + + # Validation part 3 - department + valid_depts = ['ENG', 'SALES', 'MKTG', 'HR'] + if dept not in valid_depts: + print(f"WARNING: Invalid department for {name}: {dept}") + skipped_records.append({'name': name, 'reason': 'Invalid department'}) + continue + + # Validation part 4 - hire_date + try: + dt = datetime.datetime.strptime(hire_date, '%Y-%m-%d') + except: + print(f"WARNING: Invalid hire_date for {name}: {hire_date}") + skipped_records.append({'name': name, 'reason': 'Invalid hire_date'}) + continue + + # Transformations + if dept == 'ENG': + full_dept = 'Engineering' + elif dept == 'SALES': + full_dept = 'Sales' + elif dept == 'MKTG': + full_dept = 'Marketing' + elif dept == 'HR': + full_dept = 'Human Resources' + else: + full_dept = dept + + annual_salary = sal * 12 + years_experience = (datetime.datetime.now() - dt).days / 365.25 + + processed_records.append({ + 'name': name, + 'email': email, + 'department': full_dept, + 'annual_salary': annual_salary, + 'hire_date': hire_date, + 'years_experience': round(years_experience, 2) + }) + + total_salary += annual_salary + + if full_dept not in dept_count: + dept_count[full_dept] = 0 + dept_count[full_dept] += 1 + + print(f"\nProcessed {len(processed_records)} valid records") + print(f"Skipped {len(skipped_records)} invalid records") + print(f"Total annual payroll: ${total_salary:,}") + + print("\nEmployees by department:") + for d in dept_count: + print(f" {d}: {dept_count[d]}") + + # Generate JSON output + json_data = { + 'summary': { + 'total_employees': len(processed_records), + 'skipped_records': len(skipped_records), + 'total_annual_payroll': total_salary, + 'employees_by_department': dept_count + }, + 'employees': processed_records, + 'skipped': skipped_records + } + + with open(json_output_path, 'w') as jf: + json.dump(json_data, jf, indent=2) + print(f"\nJSON report written to: {json_output_path}") + + # Generate HTML output + html_content = "Employee Report" + html_content += "

Employee Data Report

" + + html_content += "

Summary

" + html_content += "" + + html_content += "

Employees by Department

" + html_content += "" + + html_content += "

Employee Details

" + html_content += "" + html_content += "" + for emp in processed_records: + html_content += "" + html_content += f"" + html_content += f"" + html_content += f"" + html_content += f"" + html_content += f"" + html_content += f"" + html_content += "" + html_content += "
NameEmailDepartmentAnnual SalaryHire DateYears Exp
{emp['name']}{emp['email']}{emp['department']}${emp['annual_salary']:,}{emp['hire_date']}{emp['years_experience']}
" + + html_content += "

Skipped Records

" + html_content += "" + + html_content += "" + + with open(html_output_path, 'w') as hf: + hf.write(html_content) + print(f"HTML report written to: {html_output_path}") + + print("\nProcessing complete!") + + except FileNotFoundError: + print(f"ERROR: File not found: {file_path}") + except Exception as e: + print(f"ERROR: Something went wrong: {e}") + +if __name__ == "__main__": + process_employee_data() diff --git a/demo-03/employees.csv b/demo-03/employees.csv new file mode 100644 index 0000000..8d7c7da --- /dev/null +++ b/demo-03/employees.csv @@ -0,0 +1,11 @@ +name,email,department,salary,hire_date +Alice Smith,alice@example.com,ENG,75000,2023-01-15 +Bob Jones,bob@example.com,SALES,-50000,2023-02-01 +Charlie,charlie@bademail,MKTG,65000,2023-03-01 +Diana Prince,diana@example.com,ENG,82000,2022-05-20 +Eve Wilson,eve@example.com,HR,58000,2023-04-10 +Frank Miller,frank@example.com,INVALID,70000,2023-01-25 +Grace Lee,grace@example.com,SALES,0,2023-06-01 +Henry Davis,henry@example.com,ENG,90000,invalid_date +Ivy Chen,ivy@example.com,MKTG,62000,2023-07-15 +Jack Brown,jack@example.com,HR,55000,2023-08-01 diff --git a/demo-03/report.html b/demo-03/report.html new file mode 100644 index 0000000..654a1c0 --- /dev/null +++ b/demo-03/report.html @@ -0,0 +1 @@ +Employee Report

Employee Data Report

Summary

Employees by Department

Employee Details

NameEmailDepartmentAnnual SalaryHire DateYears Exp
Alice Smithalice@example.comEngineering$900,0002023-01-153.0
Diana Princediana@example.comEngineering$984,0002022-05-203.66
Eve Wilsoneve@example.comHuman Resources$696,0002023-04-102.77
Grace Leegrace@example.comSales$02023-06-012.63
Ivy Chenivy@example.comMarketing$744,0002023-07-152.51
Jack Brownjack@example.comHuman Resources$660,0002023-08-012.46

Skipped Records

\ No newline at end of file diff --git a/demo-03/report.json b/demo-03/report.json new file mode 100644 index 0000000..22c923d --- /dev/null +++ b/demo-03/report.json @@ -0,0 +1,81 @@ +{ + "summary": { + "total_employees": 6, + "skipped_records": 4, + "total_annual_payroll": 3984000, + "employees_by_department": { + "Engineering": 2, + "Human Resources": 2, + "Sales": 1, + "Marketing": 1 + } + }, + "employees": [ + { + "name": "Alice Smith", + "email": "alice@example.com", + "department": "Engineering", + "annual_salary": 900000, + "hire_date": "2023-01-15", + "years_experience": 3.0 + }, + { + "name": "Diana Prince", + "email": "diana@example.com", + "department": "Engineering", + "annual_salary": 984000, + "hire_date": "2022-05-20", + "years_experience": 3.66 + }, + { + "name": "Eve Wilson", + "email": "eve@example.com", + "department": "Human Resources", + "annual_salary": 696000, + "hire_date": "2023-04-10", + "years_experience": 2.77 + }, + { + "name": "Grace Lee", + "email": "grace@example.com", + "department": "Sales", + "annual_salary": 0, + "hire_date": "2023-06-01", + "years_experience": 2.63 + }, + { + "name": "Ivy Chen", + "email": "ivy@example.com", + "department": "Marketing", + "annual_salary": 744000, + "hire_date": "2023-07-15", + "years_experience": 2.51 + }, + { + "name": "Jack Brown", + "email": "jack@example.com", + "department": "Human Resources", + "annual_salary": 660000, + "hire_date": "2023-08-01", + "years_experience": 2.46 + } + ], + "skipped": [ + { + "name": "Bob Jones", + "reason": "Negative salary" + }, + { + "name": "Charlie", + "reason": "Invalid email" + }, + { + "name": "Frank Miller", + "reason": "Invalid department" + }, + { + "name": "Henry Davis", + "reason": "Invalid hire_date" + } + ] +} \ No newline at end of file