You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
3.2 KiB
90 lines
3.2 KiB
"""
|
|
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]
|
|
|