Bulk Import of CLIC Objects (Quotes, Agreements, Rebates)

This is shared content. It is surfaced under Quoting, Agreements & Promotions, and Rebates via the Include Page macro. Edit it here, in its canonical location — all the category wrapper pages update automatically.

This article describes the BulkImport Model Class — a reusable component for user-driven bulk creation and submission of Pricefx CLIC objects (Quotes Q, Contracts / Agreements CT, Rebate Agreements RBA) from an uploaded Excel file, inside the platform.

Two approaches to bulk creation

There are two supported in-platform patterns for creating many CLIC objects at once. They are complementary, not successive — pick the one that fits the scenario.

Aspect

CFS-based approach

Model Class approach (this article)

Scope

Quotes only

Generic across CLIC types (Q / CT / RBA), thin per-type adapters

Source of rows

User-managed Pricing Parameter table

Excel file uploaded through a guided form

Driver

A Calculated Field Set iterating the table rows

A two-step Model Class (Upload → Process) + Results dashboard

Per-row feedback

Status column written back to the source table

Outcomes persisted to a model table, rendered on a dashboard with clickable Unity deep links

Parallelism

Distributed calculation (shotgunModeEnabled)

Sequential today; parallel variant is a documented follow-up

Best for

Quote-only, minimal-footprint bulk creation

Multi-type imports wanting a guided UX, a results view, and per-run outcome tracking

The CFS-based approach is documented separately in How to Create and Submit Quotes in Bulk and remains published and valid. This page does not replace it.

If a third-party system is the orchestrator, it should call the CLIC API directly via clicmanager.create/{type} followed by clicmanager.runjob/{typedId}/{action}. Routing those creations through a Pricefx-side bulk job would only add a layer of indirection.

How it works

  1. Upload step (a configurator) — the user picks a ClicType (Q / CT / RBA) and attaches an Excel .xlsx file. CSV is not supported by this input. Once a type is chosen, the form shows the expected columns for that type.

  2. Process step (a model calculation) — rows are grouped by the type's key column; for each group it calls clicmanager.create/{type}, then hands the created object off via clicmanager.runjob/{typedId}/submit. One CLIC object is created per group.

  3. Results dashboard — per-group outcomes (created object, create/submit errors, processed date) are written to the BulkImportResults model table and rendered with live status and clickable Unity deep links. Press F5 to refresh the per-object status.

Separation of responsibilities

The pattern only scales if the creation step stays lean. The bulk job persists only the required inputs, sets the custom type so the right logics run, and triggers submission. Everything that can be reconstructed from master data — customer/product lookups, prices, discounts, margins, totals, validations, approval routing, cross-line aggregations — belongs to the Header and Line/Item logics, which run as part of submission. Anything that is a genuine deal parameter (an explicit quantity, a negotiated list price) is exactly what the bulk job persists.

Expected file shape

ClicType

Group key

Required columns

Optional columns

Q

QuoteKey

Customer, Sku, Quantity

ListPrice, TargetDate, ExpiryDate

CT

ContractKey

Customer, Sku, Quantity

ListPrice, TargetDate → startDate, ExpiryDate → endDate

RBA

RebateAgreementKey

Customer, Sku, Quantity

ListPrice, TargetDate → startDate, ExpiryDate → endDate / payoutDate

Header columns are read from the first row of each group.

The shipped sample files deliberately flatten a two-level object into one row per line (header fields and line fields side by side, grouped by the key column) to keep the samples focused on the import process. A production file would split a Header tab (one record per object) from a Line Items tab (many per object).

Architecture and adapter contract

The framework logics (BulkImport_Process, BulkImport_ResultsEval, BulkImport_Lib) are type-agnostic. They resolve a per-type adapter at runtime via libs.BulkImport_Adapter_${clicType}.Core. Each adapter implements the same six-member contract:

Member

Purpose

typeCode()

Short CLIC type code (Q, CT, RBA).

groupKeyField()

Source-row column to group on (e.g. QuoteKey).

customTypeName()

Custom type the created objects belong to (e.g. CFS_BulkQuoteType).

submitAction()

Workflow action invoked via clicmanager.runjob (typically submit).

linkFor(typedId, uniqueName)

Deep-link URL into Unity for the created object.

buildPayload(rows)

Build the clicmanager.create/${type} body for one group of rows.

To add a new CLIC type, author a new BulkImport_Adapter_<TYPE> library element implementing these six members, plus its companion header/line type artifacts. The framework logics need no changes.

Prerequisites

  • A bound system named localhost must exist on the partition (used by api.boundCall for clicmanager.create and clicmanager.runjob).

Current limitations and roadmap

The component deliberately ships lean. Known follow-ups:

  • Sequential processing. Groups are processed one at a time; a model_parallel_calculation variant (one job per group) is the documented next step. The adapter contract is already shaped for it — buildPayload takes a single group's rows and outcomes are independent per group.

  • No up-front validation. The Process step assumes valid rows and captures only the errors returned by create / submit per row. A pre-flight issue report (review before any object is created) is a candidate iteration.

  • No cross-run audit view. Each run's outcomes are persisted, but a consolidated history across runs is not yet built; the BulkImportResults model table is the natural surface for it.