Skip to content

Instantly share code, notes, and snippets.

@wbingli
Last active March 9, 2026 19:51
Show Gist options
  • Select an option

  • Save wbingli/90c8b1f5b90880cff614955d483a0b69 to your computer and use it in GitHub Desktop.

Select an option

Save wbingli/90c8b1f5b90880cff614955d483a0b69 to your computer and use it in GitHub Desktop.
Package Child Line Item Targeting Matching Rules - Investigation PAT-125

Package Child Line Item Targeting Matching Rules

Investigation Summary

Date: 2026-03-09
Context: Oncall question about package targeting validation in Mission Control

Problem Statement

Teams user asked whether child line items within a package must have matching targeting values when syncing from Operative One (O1) to Mission Control (MC), and if mismatched values (e.g., FireTV vs LGTV for device targeting) would cause a push error.

Answer

Yes — child line items within a package MUST have matching targeting values. If one child has FireTV and another has LGTV for MC_Device Name, the O1 → MC push will fail for those child line items.

Root Cause / Enforcement Point

The validation is enforced in order-manager during the O1 → MC sync pipeline, specifically in:

SalesOrderValidator.checkPackageTargets() (line 255)

  • File: order-manager/src/main/java/com/disney/digital/ads/order/manager/utils/validators/SalesOrderValidator.java

How it works

  1. Extracts all MC child line items from the package
  2. Converts each child's targeting to a JSON string (excluding exempted targets)
  3. Compares all children's targeting against the first child using JSONAssert.assertEquals() with LENIENT mode
  4. If ANY child has different targeting → validation fails

Error message on failure

"- child line item targets must match all other targets in same package"

Result: Failed child line items get status FAIL and are NOT synced to MC. Valid line items in the same package can still sync (partial success is allowed).

Targets EXCLUDED from Matching Requirement

Two targeting dimensions are excluded from the matching check (child lines CAN have different values for these):

  1. Spot Length — different child lines can have different spot lengths
  2. MC_Publisher — different child lines can have different publishers

This is implemented in SalesOrderParsingHelper.getFilteredTargetListInJsonString():

.read("$.targets.targets[?(@!=null && @.name!='Spot Length' && @.name!='MC_Publisher')]")

All other MC targets (including MC_Device Name) MUST match across child lines.

Product Content Type Exemptions

Certain product content types skip the targeting validation entirely:

Order-level skip (skips all package validations):

  • DSE, DXP

Product-level skip (individual child lines are excluded from the comparison):

  • DSE, DXP, Sports, Hulu, Deportes

Config: order-manager/config/application.properties (lines 116-117)

order.line.item.skip.validation.product.content.types=DSE,DXP
order.product.content.types.skip.targets.validation=DSE,DXP,Sports,Hulu,Deportes

Other Package Validations (for context)

In addition to targeting, order-manager validates that package children must match on:

  • Start/end dates — must match the parent package dates
  • Billable 3rd party servers — must match if package is Demo Guaranteed (Nielsen DTA)
  • DAS O1 Line Item IDs — no duplicates within the same package

Campaign-Manager Behavior

Campaign-manager does NOT enforce package-level targeting consistency. It validates individual line items independently. The package targeting matching is purely an order-manager sync-time validation.

Summary Answer to the Teams Question

Q: Do child lines within a package need matching targeting values?
A: Yes. All MC child line items in a package must have identical targeting, with two exceptions: Spot Length and MC_Publisher can differ.

Q: If one child has FireTV and another has LGTV in MC_Device Name, will it cause a push error?
A: Yes. This will cause a push error with message: "child line item targets must match all other targets in same package". The mismatched child line items will fail to sync.

Q: Are any MC targets excluded from this?
A: Yes — Spot Length and MC_Publisher are excluded. Additionally, child lines with Product Content Type of DSE, DXP, Sports, Hulu, or Deportes are exempt from the check entirely.

Classification

Expected Behavior — this is a deliberate validation rule in order-manager.

Source Code References

Main Validation Logic

File: order-manager/src/main/java/com/disney/digital/ads/order/manager/utils/validators/SalesOrderValidator.java

/**
 * All MC line items within the same package should have the same targets list
 * @param salesOrderLineItem the package that contains a pushed line item
 * @return true if passed check
 */
private boolean checkPackageTargets(JsonNode salesOrderLineItem, Map<String, Set<String>> lineItemsIdsToProductContentTypes) {
    List<String> lineItemsTargetsStringList =
        StreamSupport.stream(salesOrderParsingHelper.extractChildLineItemsListFromPackage(salesOrderLineItem).spliterator(), false)
            .filter(childNode -> salesOrderParsingHelper.isMissionControlLine(childNode)
                && !skipCheckPackageTargets(childNode, lineItemsIdsToProductContentTypes))
            .map(filteredChildNode -> salesOrderParsingHelper.getFilteredTargetListInJsonString(filteredChildNode))
            .toList();
    if (CollectionUtils.isEmpty(lineItemsTargetsStringList)) {
        return true;
    }

    try {
        String expectedTargets = lineItemsTargetsStringList.get(0);
        lineItemsTargetsStringList.forEach(targetsstring ->
            JSONAssert.assertEquals(expectedTargets, targetsstring, JSONCompareMode.LENIENT));
        return true;
    } catch (AssertionError e) {
        logger.error("Packaged line item targets do not match: {}", e.getMessage());
        return false;
    }
}

private boolean skipCheckPackageTargets(JsonNode childLineItem, Map<String, Set<String>> lineItemsIdsToSkipValidation) {
    String id = salesOrderParsingHelper.getIdFromNode(childLineItem);
    Set<String> productContentTypes = lineItemsIdsToSkipValidation.getOrDefault(id, Set.of());
    return productContentTypes.stream().anyMatch(type ->
        productContentTypesSkipTargetsValidation.stream().anyMatch(skipType -> skipType.equalsIgnoreCase(type)));
}

Target Filtering (Exclusions)

File: order-manager/src/main/java/com/disney/digital/ads/order/manager/utils/SalesOrderParsingHelper.java

public String getFilteredTargetListInJsonString(JsonNode lineItem) {
    try {
        List<Map<String, Object>> filteredTargets = JsonPath
            .read(lineItem.toString(), "$.targets.targets[?(@!=null && @.name!='Spot Length' && @.name!='MC_Publisher')]");
        return new ObjectMapper().writeValueAsString(filteredTargets);
    } catch (Exception e) {
        logger.error("Failed to get filtered targets from line item: {}", e.getMessage());
        return "";
    }
}

Related Documentation

Confluence

Architecture Context

  • Package Structure:

    • Parent line item (package): Not serveable, no targeting applied
    • Child line items: Serveable, must have matching targeting (with exceptions)
    • Standalone/Packageless line items: No package parent, validated independently
  • CQRS Pattern:

    • order-manager: O1 → MC sync pipeline (where validation occurs)
    • campaign-manager: Write side (receives validated data)
    • campaign-searcher: Read side (Elasticsearch)

Test Coverage

File: order-manager/src/test/java/com/disney/digital/ads/order/manager/utils/validators/SalesOrderValidatorTest.java

Tests verify:

  • Matching targeting validation (lines 302, 377)
  • Product content type exemptions
  • Target exclusions (Spot Length, MC_Publisher)
  • Partial sync success (valid lines sync, invalid lines fail)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment