98 lines
2.7 KiB
Python
Executable File
98 lines
2.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import csv
|
|
from decimal import Decimal, InvalidOperation
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
|
|
RAW_DIR = Path("~/master-folder/attachments/bank-statements/halifax/raw").expanduser()
|
|
CLEANED_DIR = Path("~/master-folder/attachments/bank-statements/halifax/cleaned").expanduser()
|
|
|
|
|
|
def convert(in_path: Path, out_path: Path):
|
|
with open(in_path, newline="", encoding="utf-8-sig") as f_in, \
|
|
open(out_path, "w", newline="", encoding="utf-8") as f_out:
|
|
|
|
reader = csv.DictReader(f_in)
|
|
|
|
fieldnames = ["Date", "Payee", "Description", "Amount"]
|
|
writer = csv.DictWriter(f_out, fieldnames=fieldnames)
|
|
writer.writeheader()
|
|
|
|
for row in reader:
|
|
if not row:
|
|
continue
|
|
|
|
date = (row.get("Transaction Date") or "").strip()
|
|
if not date:
|
|
continue
|
|
|
|
desc = (row.get("Transaction Description") or "").strip()
|
|
payee = desc or (row.get("Transaction Type") or "").strip()
|
|
|
|
debit_str = (row.get("Debit Amount") or "").replace(",", "").strip()
|
|
credit_str = (row.get("Credit Amount") or "").replace(",", "").strip()
|
|
|
|
amount = None
|
|
|
|
if debit_str:
|
|
try:
|
|
amount = -Decimal(debit_str)
|
|
except InvalidOperation:
|
|
continue
|
|
elif credit_str:
|
|
try:
|
|
amount = Decimal(credit_str)
|
|
except InvalidOperation:
|
|
continue
|
|
|
|
if amount is None:
|
|
continue
|
|
|
|
writer.writerow({
|
|
"Date": date,
|
|
"Payee": payee,
|
|
"Description": desc,
|
|
"Amount": f"{amount:.2f}",
|
|
})
|
|
|
|
|
|
def select_file(files: list[Path]) -> Path:
|
|
print("\nSelect a Halifax CSV to clean:\n")
|
|
for i, f in enumerate(files, start=1):
|
|
print(f"[{i}] {f.name}")
|
|
|
|
try:
|
|
choice = int(input("\nEnter number: ").strip())
|
|
return files[choice - 1]
|
|
except (ValueError, IndexError):
|
|
print("Invalid selection.")
|
|
sys.exit(1)
|
|
|
|
|
|
def main():
|
|
if not RAW_DIR.exists():
|
|
print(f"Raw directory does not exist: {RAW_DIR}")
|
|
sys.exit(1)
|
|
|
|
CLEANED_DIR.mkdir(parents=True, exist_ok=True)
|
|
|
|
csv_files = sorted(RAW_DIR.glob("*.csv"))
|
|
|
|
if not csv_files:
|
|
print("No CSV files found in raw directory.")
|
|
sys.exit(0)
|
|
|
|
in_path = select_file(csv_files)
|
|
|
|
out_name = f"{in_path.stem}-cleaned.csv"
|
|
out_path = CLEANED_DIR / out_name
|
|
|
|
convert(in_path, out_path)
|
|
print(f"\n✔ Written cleaned file to:\n{out_path}\n")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|