Skip to content

Add 'increment' conflict strategy with sequential numbering #633

@chrismazanec

Description

@chrismazanec

Feature Request

Problem

When a file already exists at the target location, the backup conflict strategy renames the existing file to filename (Backup).ext. This works but makes filenames inconsistent and harder to work with in accounting workflows.

Proposed Solution

A new conflict strategy increment that appends a sequential number to the new file when a conflict occurs.

Example:

2026-03-18_cloudflare.pdf      # first invoice
2026-03-18_cloudflare_2.pdf    # second invoice same day
2026-03-18_cloudflare_3.pdf    # third invoice same day

Use Case

When processing invoices that arrive on the same day from the same vendor (e.g. multiple Cloudflare invoices in one month billed on the same date), the current backup strategy renames the existing file to (Backup) which is unintuitive — the first file gets renamed while the second keeps the original name. Sequential numbering keeps all filenames consistent and predictable, which is important for accounting/bookkeeping workflows.

This also works across separate script runs (e.g. hourly trigger), since parentFolder.getFilesByName() checks the actual Google Drive state each time.

Implementation Sketch

The change is isolated to DriveUtils in src/lib/adapter/GDriveAdapter.ts:

  1. Add INCREMENT = "increment" to the ConflictStrategy enum
  2. Add a new case in the DriveUtils.createFile switch block:
case ConflictStrategy.INCREMENT: {
  const nameParts = filename.split(".")
  const baseName = nameParts.slice(0, -1).join(".")
  const extension = nameParts[nameParts.length - 1]
  let counter = 2
  let newFilename = `${baseName}_${counter}.${extension}`
  while (parentFolder.getFilesByName(newFilename).hasNext()) {
    counter++
    newFilename = `${baseName}_${counter}.${extension}`
  }
  file = this.createFileInParent(ctx, parentFolder, newFilename, fileData)
  break
}

Current Workaround

Including the original attachment filename in the location (e.g. _{{attachment.name}}), but this produces less clean filenames.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions