blance 86bbe685c7 Fix WinSCPnet.dll load block and trailing-quote path bug in run.bat
- Unblock-File the extracted WinSCP files after unzip: Windows tags
  downloaded files with Mark-of-the-Web, which makes Add-Type refuse to
  load WinSCPnet.dll (FileLoadException 0x80131515) until unblocked.
- run.bat passed -EntityDir "%~dp0", but %~dp0 always ends in a trailing
  backslash. cmd's argument parser treats a lone backslash before a closing
  quote as an escaped literal quote rather than the string terminator, so
  PowerShell received the path with a stray " character baked in
  (Entities\CAMBS" instead of Entities\CAMBS), breaking Test-Path. Strip the
  trailing backslash before quoting it.
2026-07-05 19:36:11 -05:00

Melissa Uploader

Automated upload tool for practice exports. Uploads insurance PDFs and patient files to the correct FTP/SFTP servers for each practice, then archives what was sent.


First-time setup

  1. Double-click setup.bat — this downloads WinSCP (needed for uploading)
  2. Set up your entity folders (see below)
  3. Double-click run-all.bat each day after running the PT STMT rename script

Daily workflow

  1. Run the PT STMT rename script manually (as usual)
  2. Double-click run-all.bat to upload everything
  3. Check the window for any failures — failed files stay in place for retry

Folder layout

run-all.bat                        <- double-click to run everything
engine.ps1
setup.bat
WinSCP\                            <- created by setup.bat automatically
Entities\
  CAMBS\
    entity.json                    <- server details for this entity
    run.bat                        <- double-click to run just CAMBS
    Export1\
      AJMAT\
        practice.json              <- only needed if AJMAT has its own FTP login
        20260629\                  <- today's insurance PDFs go here
        Archive sent to FTP\       <- uploaded date folders move here
        Patient\
          Export\
            PT STMT_20260629\      <- created by rename script
            Archive Sent to FTP\   <- uploaded patient folders move here
      CIIR\
        ...
  CONSensio\
    entity.json
    ...

The two config files

There are two JSON files, and they work together — one sets the defaults for the whole entity, the other overrides just what's different for one practice.

  • entity.json — lives in the entity folder (e.g. Entities\CAMBS\entity.json). Required. This is the default server info used by every practice under that entity: which server, which login, which folder paths.
  • practice.json — lives inside one practice's folder (e.g. Entities\CAMBS\Export1\AJMAT\practice.json). Optional — only add it if a practice needs something different from entity.json. Whatever fields you put in here replace the matching field from entity.json for that practice only; anything you leave out still comes from entity.json.

Common reasons to add a practice.json:

  • The practice has its own separate FTP/SFTP login instead of the shared one
  • The practice's files need to go to a different folder path on the server than the standard {practice} pattern (e.g. the imaging vendor set it up with a different folder name, or a nonstandard structure) — override insurance_path, pdf_path, and/or patient_path to whatever that practice actually needs

You can mix and match — e.g. override just pdf_path for one practice and leave its login and every other path alone.

entity.json

  1. Create a folder under Entities\ with the entity name (e.g. Entities\CAMBS\)
  2. Copy run.bat into it
  3. Create entity.json in that folder — copy from Entities\EXAMPLE\entity.json and fill in:
Setting What to put
workflow insurance if no patient files, insurance+patient if both
ftps.host FTP server address
ftps.username FTP username (shared across all practices)
ftps.password FTP password
ftps.tls true for FTPS (secure), false for plain FTP
ftps.insurance_path Remote path for insurance PDFs — keep {practice} in it
ftps.pdf_path Remote path for PT STMT PDFs — keep {practice} in it
sftp.host SFTP server (only needed if workflow is insurance+patient)
sftp.username SFTP username
sftp.password SFTP password
sftp.patient_path Remote path for patient files — keep {practice} in it
  1. Create the Export1\ folder and a subfolder for each practice inside the entity folder

{practice} in any path gets automatically replaced with that practice's folder name — so one entity.json can serve every practice as long as they all follow the same folder-naming pattern on the server.


practice.json — overriding one practice

If one practice needs a different login, a different folder path, or both:

  1. Create a practice.json file inside that practice's folder
  2. Copy from Entities\EXAMPLE\Export1\PRACTICE_NAME\practice.json
  3. Delete every line you don't need to change — keep only the fields that differ for this practice. Everything you delete falls back to entity.json.

Example — this practice only has its own PDF folder name, nothing else differs:

{
  "ftps": {
    "pdf_path": "/{practice}/PDF_Statements_Custom"
  }
}

Example — this practice has its own SFTP login but uses the same paths as everyone else:

{
  "sftp": {
    "username": "ajmat-sftp-user",
    "password": "ajmat-sftp-pass"
  }
}

Something went wrong?

  • Files failed to upload — they stay in the date folder. Fix the issue and run again.
  • A date folder is still there after running — one or more files failed. Check the output window.
  • WinSCP error on startup — run setup.bat again to re-download WinSCP.
S
Description
Automated FTPS/SFTP upload tool for practice exports
Readme
126 KiB
Languages
PowerShell 98.2%
Batchfile 1.8%