From 960248b825beeb894026277f5ceaa6a4620e0a37 Mon Sep 17 00:00:00 2001 From: dat972 Date: Mon, 24 Aug 2026 21:50:30 -0500 Subject: [PATCH] added some more generic handling of TR products instead of hard coding UltraTax. We now have a list we loop through for things like Planner and Practice CS and can add more later --- README.md | 4 ++-- fccs_config.py | 31 ++++++++++++++++++++----------- fccs_folders.template.txt | 3 ++- fccs_reorganize.py | 3 ++- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 5f525f7..a3a97f4 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Extracts and organizes documents from FileCabinet CS (Thomson Reuters) using GUI ## Setup Per Engagement 1. Edit `config.ini` -- point `backup_dir`, `export_dir`, and `output_dir` at the client's directories. This file is created automatically from `config.template.ini` the first time you run any script (it's git-ignored, so your machine-specific paths never drift the repo). To reset a machine, delete `config.ini` and re-run. Keep shared/default changes in `config.template.ini` (the tracked file). -2. Populate `fccs_folders.txt` -- open FCCS > System Configuration > Document Folders and list each folder template exactly as shown, one per line. Keep the `YYYY` prefix on recurring folders. UltraTax CS folders are detected automatically and do not need to be listed. Like `config.ini`, this file is auto-created from `fccs_folders.template.txt` on first use and is git-ignored — edit it freely per engagement; put only broadly-useful defaults in the tracked template. +2. Populate `fccs_folders.txt` -- open FCCS > System Configuration > Document Folders and list each folder template exactly as shown, one per line. Keep the `YYYY` prefix on recurring folders. Thomson Reuters product folders (UltraTax CS, Planner CS, Practice CS) are detected automatically and do not need to be listed. Like `config.ini`, this file is auto-created from `fccs_folders.template.txt` on first use and is git-ignored — edit it freely per engagement; put only broadly-useful defaults in the tracked template. ## Workflow @@ -95,7 +95,7 @@ output/ (only files whose client couldn't be recovered from the filename) ``` -Exported filenames follow the format `{drawer_id}_{client_name}_{folder_name}_{creation_date}_{document_name}.ext`. The parser uses folder templates from `fccs_folders.txt` (with `YYYY` expanded via regex) and the creation date (`MM-DD-YYYY`) as anchors to reliably split the underscore-delimited fields. Folder names are decomposed into nested paths that match the FCCS UI structure (e.g. `2025 Tax Documents` becomes `Tax Documents/2025/`). UltraTax CS folders are matched by a built-in pattern. +Exported filenames follow the format `{drawer_id}_{client_name}_{folder_name}_{creation_date}_{document_name}.ext`. The parser uses folder templates from `fccs_folders.txt` (with `YYYY` expanded via regex) and the creation date (`MM-DD-YYYY`) as anchors to reliably split the underscore-delimited fields. Folder names are decomposed into nested paths that match the FCCS UI structure (e.g. `2025 Tax Documents` becomes `Tax Documents/2025/`). Thomson Reuters product folders — `{Product} MM-DD-YYYY`, e.g. UltraTax CS, Planner CS, Practice CS — are matched by a built-in pattern and become `{Product}/{date}/`; to support another product, add its name to `TR_PRODUCT_FOLDERS` in `fccs_config.py`. FCCS drawers can (rarely) contain **nested subfolders** under a template folder; the export encodes these in square brackets appended to the folder field, e.g. `2016 Income Documents[4201 N Beach Street, LLC]`. The reorganizer recreates them as deeper nesting — that example becomes `Income Documents/2016/4201 N Beach Street, LLC/` — as long as the parent (`YYYY Income Documents`) is a listed template; no bracket entries are needed in `fccs_folders.txt`. diff --git a/fccs_config.py b/fccs_config.py index 780e344..fe5c57a 100644 --- a/fccs_config.py +++ b/fccs_config.py @@ -105,30 +105,38 @@ def load_folder_list(path): return folders +# Thomson Reuters product integrations that auto-generate folders named +# "{Product} MM-DD-YYYY" in FCCS. Matched built-in (no fccs_folders.txt entry +# needed); add newly-discovered products here. +TR_PRODUCT_FOLDERS = ("UltraTax CS", "Planner CS", "Practice CS") + + def build_folder_patterns(templates): """ Convert folder template strings into regex patterns for matching. Templates use YYYY as a year placeholder (e.g. 'YYYY Tax Documents'). Non-recurring folders (no YYYY) are matched literally. - A built-in pattern for 'UltraTax CS MM-DD-YYYY' is always included. + Built-in patterns for '{Product} MM-DD-YYYY' Thomson Reuters product + folders (TR_PRODUCT_FOLDERS, e.g. UltraTax CS) are always included. Returns a list of (compiled_regex, template_name, folder_type) tuples, sorted longest-first to prevent partial matches. folder_type is one of: "yyyy" — recurring folder with year prefix (captured in group 1) - "ultratax" — UltraTax CS folder with date suffix (captured in group 1) + "ultratax" — TR product folder with date suffix (captured in group 1) "static" — non-recurring folder, no decomposition needed """ patterns = [] - # Built-in: UltraTax CS folders (auto-generated by UltraTax integration) - patterns.append(( - re.compile(r"UltraTax CS (\d{2}-\d{2}-\d{4})$"), - "UltraTax CS", - "ultratax", - )) + # Built-in: TR product folders (auto-generated by each product's integration) + for product in TR_PRODUCT_FOLDERS: + patterns.append(( + re.compile(re.escape(product) + r" (\d{2}-\d{2}-\d{4})$"), + product, + "ultratax", + )) for tmpl in templates: if "YYYY" in tmpl: @@ -156,8 +164,9 @@ def decompose_folder_path(match, folder_type, template_name): Examples: yyyy: "YYYY Tax Documents" matched "2025 Tax Documents" → ("Tax Documents", "2025") - ultratax: "UltraTax CS 12-31-2008" - → ("UltraTax CS", "12-31-2008") + ultratax: any TR product folder, e.g. "UltraTax CS 12-31-2008" + → ("UltraTax CS", "12-31-2008"), + "Planner CS 12-31-2016" → ("Planner CS", "12-31-2016") static: "Permanent File" → ("Permanent File",) """ @@ -168,7 +177,7 @@ def decompose_folder_path(match, folder_type, template_name): return (base_name, year) elif folder_type == "ultratax": date = match.group(1) - return ("UltraTax CS", date) + return (template_name, date) else: return (template_name,) diff --git a/fccs_folders.template.txt b/fccs_folders.template.txt index 977158c..757927b 100644 --- a/fccs_folders.template.txt +++ b/fccs_folders.template.txt @@ -6,7 +6,8 @@ # # List folder names exactly as shown in FCCS System Configuration > Document Folders. # Keep the YYYY prefix for recurring folders. Non-recurring folders go as-is. -# UltraTax CS folders are handled automatically — do not list them here. +# Thomson Reuters product folders (UltraTax CS, Planner CS, Practice CS) are +# handled automatically — do not list them here. # Blank lines and lines starting with # are ignored. # # Examples: diff --git a/fccs_reorganize.py b/fccs_reorganize.py index 7ac7889..32a3064 100644 --- a/fccs_reorganize.py +++ b/fccs_reorganize.py @@ -141,7 +141,8 @@ def main(): folder_templates = load_folder_list(folder_list_path) if not folder_templates: - log("WARNING: folder list is empty. Only built-in patterns (UltraTax CS) will match.") + log("WARNING: folder list is empty. Only built-in patterns (UltraTax CS, " + "Planner CS, Practice CS) will match.") folder_patterns = build_folder_patterns(folder_templates) log(f"Loaded {len(folder_patterns)} folder patterns")