Skip to content

feat: report auto-bumped version on form replace#3125

Open
kelvin-muchiri wants to merge 2 commits into
mainfrom
communicate-version-bump-on-replace
Open

feat: report auto-bumped version on form replace#3125
kelvin-muchiri wants to merge 2 commits into
mainfrom
communicate-version-bump-on-replace

Conversation

@kelvin-muchiri

@kelvin-muchiri kelvin-muchiri commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Changes / Features implemented

Follow-up to #3075. When a form is replaced with an XLSForm that reuses an existing version string, onadata auto-bumps the version (-2, -3, …). Previously this happened silently — the client was never told. This surfaces it on the replace response (PATCH /api/v1/forms/{pk}), mirroring the existing has_id_string_changed pattern.

  • Track the change via a transient _version_changed flag on DataDictionary (set in save() for the XLS path and in publish_xml_form for the XML path), exposed as the XForm.has_version_changed property.
  • Add XFormUpdateSerializer (adds only has_version_changed, no has_id_string_changed coupling) and use it in _try_update_xlsform.
  • Serialize the freshly-published form instead of the stale pre-replace object, so the returned version reflects the bump (also fixes a latent staleness bug where the replace response returned the old version).

The client reads both answers from the replace response: "to what?" via the existing version field (now accurate), and "was it auto-bumped?" via has_version_changed. has_version_changed is True only when the submitted version collided with an existing XFormVersion; it is scoped to the replace response and absent from form GET/list responses.

Steps taken to verify this change does what is intended

Added/extended tests in test_xform_viewset.py, run via docker (no regressions against existing form-replacement tests):

  • Same-version replace: response version is the bumped value and has_version_changed is True.
  • New-version replace (transportation_version.xlsx): version used as-is, has_version_changed is False.
  • Plain form retrieve: has_version_changed absent (confirms scoping).

Side effects of implementing this change

  • The PATCH /api/v1/forms/{pk} replace response now serializes the freshly-published form rather than the stale pre-replace object, and gains a has_version_changed boolean field. Both are additive; the previously-stale version field is now correct.

Before submitting this PR for review, please make sure you have:

  • Included tests
  • Updated documentation

Closes #

When a form is replaced with an XLSForm that reuses an existing version
string, the version is auto-bumped (-2, -3, ...). Communicate that back
to the client, mirroring has_id_string_changed:

- track the change via a transient _version_changed flag on
  DataDictionary, exposed as XForm.has_version_changed
- add XFormUpdateSerializer (version-only) and use it for the replace
  response, serializing the freshly-published form so the returned
  version reflects the bump
- has_version_changed is True only when the version was bumped
Prospector (pylint protected-access) flagged setting dd._version_changed
on an external object. Scope a pylint disable to that line and reuse the
computed version_changed boolean.
@kelvin-muchiri kelvin-muchiri requested a review from ukanga June 10, 2026 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant