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 += f"- Total Employees: {len(processed_records)}
"
+ html_content += f"- Skipped Records: {len(skipped_records)}
"
+ html_content += f"- Total Annual Payroll: ${total_salary:,}
"
+ html_content += "
"
+
+ html_content += "Employees by Department
"
+ html_content += ""
+ for d in dept_count:
+ html_content += f"- {d}: {dept_count[d]}
"
+ html_content += "
"
+
+ html_content += "Employee Details
"
+ html_content += ""
+ html_content += "| Name | Email | Department | Annual Salary | Hire Date | Years Exp |
"
+ for emp in processed_records:
+ html_content += ""
+ html_content += f"| {emp['name']} | "
+ html_content += f"{emp['email']} | "
+ html_content += f"{emp['department']} | "
+ html_content += f"${emp['annual_salary']:,} | "
+ html_content += f"{emp['hire_date']} | "
+ html_content += f"{emp['years_experience']} | "
+ html_content += "
"
+ html_content += "
"
+
+ html_content += "Skipped Records
"
+ html_content += ""
+ for skipped in skipped_records:
+ html_content += f"- {skipped['name']}: {skipped['reason']}
"
+ 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 ReportEmployee Data Report
Summary
- Total Employees: 6
- Skipped Records: 4
- Total Annual Payroll: $3,984,000
Employees by Department
- Engineering: 2
- Human Resources: 2
- Sales: 1
- Marketing: 1
Employee Details
| Name | Email | Department | Annual Salary | Hire Date | Years Exp |
|---|
| Alice Smith | alice@example.com | Engineering | $900,000 | 2023-01-15 | 3.0 |
| Diana Prince | diana@example.com | Engineering | $984,000 | 2022-05-20 | 3.66 |
| Eve Wilson | eve@example.com | Human Resources | $696,000 | 2023-04-10 | 2.77 |
| Grace Lee | grace@example.com | Sales | $0 | 2023-06-01 | 2.63 |
| Ivy Chen | ivy@example.com | Marketing | $744,000 | 2023-07-15 | 2.51 |
| Jack Brown | jack@example.com | Human Resources | $660,000 | 2023-08-01 | 2.46 |
Skipped Records
- Bob Jones: Negative salary
- Charlie: Invalid email
- Frank Miller: Invalid department
- Henry Davis: Invalid hire_date
\ 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