""" Hold Reconciler is an application meant to help reconcile the differences in payments that marked as on hold in Great Plains and OnBase. It takes a report csv from OnBase and a report from GreatPlains and checks them against each other. It attempts to make them based on contract number and payment amount, or just the contract number. It also does a lot of filtering for the Great Plains report to remove irrelevant data. *Last Updated: version 1.3* *Originally developed in Spring of 2023 by Griffiths Lott (g@glott.me)* """ import re from re import Pattern import os from os.path import basename import glob import logging from pathlib import Path from tomllib import load from pandas import DataFrame, Series from typing import TypeVar, Literal import logging.config from logging import getLogger logger = getLogger(__name__) CN_REGEX = re.compile(r"\d{7}(-\d{3})?") def setup_logging(): """ Sets up logging configuration from the TOML file. If the logging configuration fails to be loaded from the file, a default logging configuration is used instead. Returns: logging.Logger: The logger instance. """ with open("config_logger.toml", "rb") as f: config_dict: dict = load(f) try: # Try to load logging configuration from the TOML file logging.config.dictConfig(config_dict) except Exception as e: # If the logging configuration fails, use a default configuration and log the error logger = logging.getLogger() logger.setLevel(logging.DEBUG) logger.warning("Failed setting up logger!") logger.exception(e) logger.warning(f"Config:\n{config_dict}") return logger def drop_unnamed(df: DataFrame, inplace: bool = True) -> DataFrame|None: """ Drops all Unnamed columns from a dataframe. ### CAUTION : This function acts *inplace* by deafult (on the orignal dataframe, not a copy!) """ cols = [c for c in df.columns if "Unnamed" in c] return df.drop(cols, axis=1, inplace=inplace) def find_most_recent_file(folder_path: Path, file_pattern: Pattern) -> str: """ Given a folder path and a regular expression pattern, this function returns the path of the most recently modified file in the folder that matches the pattern. Args: folder_path (Path): A pathlib.Path object representing the folder to search. file_pattern (Pattern): A regular expression pattern used to filter the files in the folder. Returns: str: The path of the most recently modified file in the folder that matches the pattern. """ # Find all files in the folder that match the pattern files = glob.glob(f"{folder_path}/*") logger.debug(f"files: {files}") # Get the modification time of each file and filter to only those that match the pattern file_times = [(os.path.getmtime(path), path) for path in files if re.match(file_pattern, basename(path))] # Sort the files by modification time (most recent first) file_times.sort(reverse=True) logger.debug(f"file times: {file_times}") # Return the path of the most recent file return file_times[0][1]