Skip to content

Commit 63fbb0a

Browse files
committed
Add script template
1 parent b6945b6 commit 63fbb0a

File tree

2 files changed

+79
-17
lines changed

2 files changed

+79
-17
lines changed

scripts/process_amex_expenses.py

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
#!/usr/bin/env python3
2-
"""
1+
#!/usr/bin/env python
2+
"""Script for processing American Express activity CSV into cleaned Excel file.
3+
34
Process American Express activity CSV into a cleaned Excel file with columns:
45
- Date (transaction date)
56
- Source ("American Express Cobalt")
@@ -8,9 +9,17 @@
89
- Anvita Paid (amount if Card Member is Anvita Akkur; else 0)
910
- Taylor Portion (0.6 if groceries; else blank)
1011
11-
Usage:
12-
python process_amex_expenses.py --input activity.csv \\
13-
--output amex_expenses_full.xlsx
12+
Usage Examples:
13+
# Basic usage
14+
python -m scripts.process_amex_expenses --input activity.csv --output expenses.xlsx
15+
16+
# Show help
17+
python -m scripts.process_amex_expenses --help
18+
19+
Requirements:
20+
- pandas library for CSV/Excel processing
21+
- Input CSV must have columns: Date, Description, Card Member, Amount
22+
- Positive amounts are treated as expenses, negative as payments/credits
1423
"""
1524

1625
import argparse
@@ -58,11 +67,26 @@ def is_grocery(merchant: str) -> bool:
5867
return any(pattern.search(merchant) for pattern in GROCERY_PATTERNS)
5968

6069

70+
def paid_for(row: pd.Series[Any], who: str) -> float:
71+
"""Calculate amount paid by specific person based on Card Member field."""
72+
cm = str(row.get("Card Member", "")).upper()
73+
return float(row["Amount"]) if who in cm else 0.0
74+
75+
6176
def main() -> None:
62-
p = argparse.ArgumentParser()
63-
p.add_argument("--input", "-i", required=True, help="Path to Amex activity CSV")
64-
p.add_argument("--output", "-o", required=True, help="Path to output Excel file")
65-
args = p.parse_args()
77+
"""Main function for process_amex_expenses."""
78+
parser = argparse.ArgumentParser(
79+
description="Process American Express activity CSV into cleaned Excel file"
80+
)
81+
82+
parser.add_argument(
83+
"--input", "-i", type=str, required=True, help="Path to Amex activity CSV"
84+
)
85+
parser.add_argument(
86+
"--output", "-o", type=str, required=True, help="Path to output Excel file"
87+
)
88+
89+
args = parser.parse_args()
6690

6791
# Read CSV (expects columns like: Date, Date Processed, Description,
6892
# Card Member, Account #, Amount)
@@ -72,8 +96,8 @@ def main() -> None:
7296
print(f"Error reading input CSV: {e}", file=sys.stderr)
7397
sys.exit(1)
7498

75-
# Keep only expenses (positive amounts). Payments/credits are negative in
76-
# Amex export.
99+
# Keep only expenses (positive amounts).
100+
# Payments/credits are negative in Amex export.
77101
if "Amount" not in df.columns:
78102
print("Input CSV missing 'Amount' column.", file=sys.stderr)
79103
sys.exit(1)
@@ -85,26 +109,24 @@ def main() -> None:
85109
print(f"Input CSV missing '{col}' column.", file=sys.stderr)
86110
sys.exit(1)
87111

88-
# Transform
112+
# Transform data
89113
expenses["Expense"] = expenses["Description"].apply(clean_description)
90114
expenses["Source"] = "American Express Cobalt"
91-
92-
def paid_for(row: pd.Series[Any], who: str) -> float:
93-
cm = str(row.get("Card Member", "")).upper()
94-
return float(row["Amount"]) if who in cm else 0.0
95-
96115
expenses["Taylor Paid"] = expenses.apply(lambda r: paid_for(r, TAYLOR_NAME), axis=1)
97116
expenses["Anvita Paid"] = expenses.apply(lambda r: paid_for(r, ANVITA_NAME), axis=1)
98117
expenses["Taylor Portion"] = expenses["Expense"].apply(
99118
lambda x: 0.6 if is_grocery(x) else ""
100119
)
101120

121+
# Select output columns
102122
out = expenses[
103123
["Date", "Source", "Expense", "Taylor Paid", "Anvita Paid", "Taylor Portion"]
104124
].copy()
105125

126+
# Write Excel file
106127
try:
107128
out.to_excel(args.output, index=False)
129+
print(f"Successfully processed {len(out)} expenses to {args.output}")
108130
except Exception as e:
109131
print(f"Error writing Excel: {e}", file=sys.stderr)
110132
sys.exit(1)

scripts/template_script.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env python
2+
"""Script for [DESCRIPTION].
3+
4+
[More detailed description of what the script does]
5+
6+
Usage Examples:
7+
# Basic usage
8+
python -m scripts.[SCRIPT_NAME]
9+
10+
# With options
11+
python -m scripts.[SCRIPT_NAME] --option value
12+
13+
# Show help
14+
python -m scripts.[SCRIPT_NAME] --help
15+
16+
Requirements:
17+
- [List any prerequisites or setup needed]
18+
- [Dependencies, config files, etc.]
19+
"""
20+
21+
import argparse
22+
23+
24+
def main() -> None:
25+
"""Main function for [SCRIPT_NAME]."""
26+
parser = argparse.ArgumentParser(description="[DESCRIPTION]")
27+
28+
# Add script-specific arguments.
29+
parser.add_argument("--option", help="Description of option", type=str)
30+
31+
# Parse and unpack arguments.
32+
args = parser.parse_args()
33+
input: str = args.input
34+
35+
# Your script logic here
36+
print(f"Script completed successfully for input '{input}'.")
37+
38+
39+
if __name__ == "__main__":
40+
main()

0 commit comments

Comments
 (0)