feat: map Adobe Sign conditional logic to DocuSign conditionalParentLabel/Value
Adobe Sign conditionalAction (SHOW/EQUALS) is now translated to DocuSign's conditionalParentLabel + conditionalParentValue on the dependent tab, making conditional fields work in the migrated template. For radio groups, conditionalParentLabel matches the radio group name. Unsupported cases emit warnings rather than silently dropping conditions: - HIDE action (no DocuSign equivalent — field left always visible) - Non-EQUALS operators (skipped) - Multi-predicate ANY/ALL (first EQUALS predicate used, rest ignored) Also updates field-mapping.md: adds Conditional Logic Mapping table and moves this item out of Known Gaps into documented behaviour. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ad0131c2d9
commit
785107e8de
|
|
@ -80,11 +80,28 @@ Tab types that do not merge (only first location used or handled specially):
|
||||||
`radioGroupTabs` — each location is one radio button within the group
|
`radioGroupTabs` — each location is one radio button within the group
|
||||||
`signerAttachmentTabs` — each location is an independent attachment request
|
`signerAttachmentTabs` — each location is an independent attachment request
|
||||||
|
|
||||||
|
## Conditional Logic Mapping
|
||||||
|
|
||||||
|
Adobe Sign `conditionalAction` → DocuSign `conditionalParentLabel` + `conditionalParentValue` on the dependent tab.
|
||||||
|
|
||||||
|
| Adobe Sign | DocuSign | Notes |
|
||||||
|
|-----------------------------------|---------------------------------|-------|
|
||||||
|
| `predicates[].fieldName` | `conditionalParentLabel` | For radio groups, matches the group name |
|
||||||
|
| `predicates[].value` | `conditionalParentValue` | The value the trigger must equal to reveal the tab |
|
||||||
|
| `action: SHOW` | Supported | Tab is hidden until condition is met |
|
||||||
|
| `action: HIDE` | **Not supported** | No DocuSign equivalent — condition skipped, field always shown |
|
||||||
|
| `operator: EQUALS` | Supported | Only operator DocuSign supports |
|
||||||
|
| Other operators | **Not supported** | Condition skipped, warning logged |
|
||||||
|
| Multiple predicates (ANY/ALL) | **Partial** — first EQUALS only | Warning logged; remaining predicates ignored |
|
||||||
|
|
||||||
## Known Gaps
|
## Known Gaps
|
||||||
|
|
||||||
- **Conditional logic**: Adobe Sign conditional show/hide rules are not mapped.
|
- **Conditional HIDE**: Adobe Sign can conditionally hide a field. DocuSign only supports
|
||||||
DocuSign supports conditional tabs but the logic structure differs — manual
|
revealing hidden fields — there is no native way to hide a visible field conditionally.
|
||||||
rewrite required per template.
|
Templates with HIDE conditions will have those fields always visible after migration.
|
||||||
|
- **Multi-predicate conditions**: Adobe Sign supports ANY/ALL of multiple predicates.
|
||||||
|
DocuSign only supports a single parent condition per tab. Only the first EQUALS
|
||||||
|
predicate is mapped; complex conditions require manual rework.
|
||||||
- **DocuSign formula fields**: No Adobe Sign equivalent — flag for manual rewrite.
|
- **DocuSign formula fields**: No Adobe Sign equivalent — flag for manual rewrite.
|
||||||
- **Advanced field validation**: Adobe regex/custom script validation is not mapped;
|
- **Advanced field validation**: Adobe regex/custom script validation is not mapped;
|
||||||
best-effort via standard DocuSign validation types only.
|
best-effort via standard DocuSign validation types only.
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,14 @@ Field type coverage:
|
||||||
Partial: FILE_CHOOSER → signerAttachmentTabs (with warning)
|
Partial: FILE_CHOOSER → signerAttachmentTabs (with warning)
|
||||||
STAMP → stampTabs (requires stamp feature enabled on DocuSign account — warning logged)
|
STAMP → stampTabs (requires stamp feature enabled on DocuSign account — warning logged)
|
||||||
Skipped: INLINE_IMAGE, PARTICIPATION_STAMP (no DocuSign equivalent — warning logged)
|
Skipped: INLINE_IMAGE, PARTICIPATION_STAMP (no DocuSign equivalent — warning logged)
|
||||||
|
|
||||||
|
Conditional logic:
|
||||||
|
Mapped: Single-predicate SHOW conditions (EQUALS operator) →
|
||||||
|
conditionalParentLabel + conditionalParentValue on the dependent tab.
|
||||||
|
For radio groups the parentLabel matches the radio group name.
|
||||||
|
Warnings: Multi-predicate ANY/ALL conditions (only first EQUALS predicate mapped),
|
||||||
|
HIDE action (not supported in DocuSign — condition skipped),
|
||||||
|
non-EQUALS operators (skipped).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
|
@ -142,6 +150,72 @@ def _sized_tabs(locations: list, label: str, extra: dict | None = None) -> list:
|
||||||
return [_make_sized_tab(loc, label, extra) for loc in locations]
|
return [_make_sized_tab(loc, label, extra) for loc in locations]
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Conditional logic
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _apply_conditional_to_tabs(tabs: dict, field: dict, warnings: list) -> dict:
|
||||||
|
"""
|
||||||
|
Apply DocuSign conditionalParentLabel / conditionalParentValue to tabs based
|
||||||
|
on an Adobe Sign conditionalAction.
|
||||||
|
|
||||||
|
Adobe Sign model:
|
||||||
|
conditionalAction.predicates[].{fieldName, operator, value}, action=SHOW|HIDE
|
||||||
|
|
||||||
|
DocuSign model (on the dependent tab):
|
||||||
|
conditionalParentLabel — tabLabel or radioGroup groupName of the trigger tab
|
||||||
|
conditionalParentValue — value the trigger must have to reveal this tab
|
||||||
|
|
||||||
|
Mapping limitations:
|
||||||
|
- Only SHOW action is supported. DocuSign has no native HIDE — condition skipped.
|
||||||
|
- Only EQUALS operator is supported. Others are skipped.
|
||||||
|
- Only one predicate is mapped. Multi-predicate ANY/ALL logic is not supported;
|
||||||
|
the first EQUALS predicate is used and a warning is logged.
|
||||||
|
"""
|
||||||
|
if not tabs:
|
||||||
|
return tabs
|
||||||
|
|
||||||
|
ca = field.get("conditionalAction", {})
|
||||||
|
predicates = ca.get("predicates", [])
|
||||||
|
if not predicates:
|
||||||
|
return tabs # No conditions — field is always visible
|
||||||
|
|
||||||
|
label = field.get("name", "unnamed")
|
||||||
|
action = ca.get("action", "SHOW")
|
||||||
|
|
||||||
|
if action != "SHOW":
|
||||||
|
warnings.append(
|
||||||
|
f"Conditional '{label}': action={action} is not supported in DocuSign "
|
||||||
|
f"(only SHOW is supported) — condition skipped"
|
||||||
|
)
|
||||||
|
return tabs
|
||||||
|
|
||||||
|
predicate = next((p for p in predicates if p.get("operator") == "EQUALS"), None)
|
||||||
|
if not predicate:
|
||||||
|
warnings.append(
|
||||||
|
f"Conditional '{label}': no EQUALS predicate found "
|
||||||
|
f"(operators: {[p.get('operator') for p in predicates]}) — condition skipped"
|
||||||
|
)
|
||||||
|
return tabs
|
||||||
|
|
||||||
|
if len(predicates) > 1:
|
||||||
|
warnings.append(
|
||||||
|
f"Conditional '{label}': {len(predicates)} predicates with "
|
||||||
|
f"anyOrAll={ca.get('anyOrAll')} — only first EQUALS predicate mapped, "
|
||||||
|
f"remaining conditions ignored"
|
||||||
|
)
|
||||||
|
|
||||||
|
parent_label = predicate["fieldName"]
|
||||||
|
parent_value = predicate["value"]
|
||||||
|
|
||||||
|
for tab_list in tabs.values():
|
||||||
|
for tab in tab_list:
|
||||||
|
tab["conditionalParentLabel"] = parent_label
|
||||||
|
tab["conditionalParentValue"] = parent_value
|
||||||
|
|
||||||
|
return tabs
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Tab builder
|
# Tab builder
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -309,6 +383,7 @@ def compose_template(template_dir: str, output_path: str) -> tuple[dict, list[st
|
||||||
if idx >= len(signers):
|
if idx >= len(signers):
|
||||||
idx = 0
|
idx = 0
|
||||||
tabs = build_tabs_for_field(field, warnings)
|
tabs = build_tabs_for_field(field, warnings)
|
||||||
|
tabs = _apply_conditional_to_tabs(tabs, field, warnings)
|
||||||
signers[idx]["tabs"] = merge_tabs(signers[idx]["tabs"], tabs)
|
signers[idx]["tabs"] = merge_tabs(signers[idx]["tabs"], tabs)
|
||||||
|
|
||||||
template = {
|
template = {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue