Skip to content

Product Design

albert.collections.product_design.ProductDesignCollection

ProductDesignCollection(*, session: AlbertSession)

Bases: BaseCollection

Unpack formulated products into their full substance-level composition.

"Product design" here refers to unpacking (flattening) a formulation inventory item into its full substance-level composition. An unpacked product resolves a formulation's complete substance composition by recursively traversing its ingredient tree: each sub-formulation is expanded into its own ingredients, with fractional contributions multiplied down through each level and summed at the CAS-number level. It produces two outputs: a row-level inventory list (the direct worksheet ingredients, some of which may themselves be sub-formulations) and a flat CAS-level substance list (fully resolved raw materials with combined weight fractions).

The calculation assumes a non-reactive, homogeneous mixture: no chemical transformations occur and concentrations are additive. When a formulation has overrides, the recursive traversal short-circuits; Albert accepts the declared composition at face value rather than deriving it, and CAS amounts are expressed as ranges to signal supplied (not bottom-up calculated) values.

Use this when you need the resolved composition of a formula rather than just its immediate ingredient list, for example to compute regulatory or safety rollups. The formulas being unpacked are Inventory Items in the Formulas category (see InventoryCollection), and the substances resolve to CAS entries (see CasCollection).

This collection is accessed as client.product_design.

Example

from albert import Albert
client = Albert()
unpacked = client.product_design.get_unpacked_products(
    inventory_ids=["INVA9999999", "INVA9999998"],
)
for product in unpacked:
    for ingredient in product.inventories or []:
        print(ingredient.name, ingredient.value)

Parameters:

Name Type Description Default
session AlbertSession

The authenticated Albert session used for API calls.

required

Attributes:

Name Type Description
base_path str

The base API route for product design requests.

Methods:

Name Description
get_unpacked_products

Unpack one or more formulas into their full CAS-level substance composition.

Parameters:

Name Type Description Default
session AlbertSession

The authenticated Albert session used for API calls.

required
Source code in src/albert/collections/product_design.py
def __init__(self, *, session: AlbertSession):
    """Initialize a ProductDesignCollection.

    Parameters
    ----------
    session : AlbertSession
        The authenticated Albert session used for API calls.
    """
    super().__init__(session=session)
    self.base_path = f"/api/{ProductDesignCollection._api_version}/productdesign"

base_path

base_path = f"/api/{ProductDesignCollection._api_version}/productdesign"

get_unpacked_products

get_unpacked_products(
    *,
    inventory_ids: list[InventoryId],
    unpack_id: Literal[
        "DESIGN", "PREDICTION"
    ] = "PREDICTION",
) -> list[UnpackedProductDesign]

Unpack formulas into their full CAS-level substance composition.

Each supplied formula is flattened into its constituent substances, with their amounts, CAS information, and SDS / regulatory details. One UnpackedProductDesign is returned per input formula. Requests are automatically split into batches of 50 inventory IDs, so large lists can be passed in a single call.

Example

unpacked = client.product_design.get_unpacked_products(
    inventory_ids=["INVA9999999"],
    unpack_id="DESIGN",
)
substances = unpacked[0].cas_level_substances or []
for substance in substances:
    print(substance.cas_id, substance.amount)

Parameters:

Name Type Description Default
inventory_ids list[InventoryId]

The formula Inventory IDs to unpack (format INV..., e.g. "INVA9999999").

required
unpack_id (DESIGN, PREDICTION)

Which unpacking mode the server should use. Defaults to "PREDICTION".

"DESIGN"

Returns:

Type Description
list[UnpackedProductDesign]

The unpacked composition, one entry per input formula.

Source code in src/albert/collections/product_design.py
@validate_call
def get_unpacked_products(
    self,
    *,
    inventory_ids: list[InventoryId],
    unpack_id: Literal["DESIGN", "PREDICTION"] = "PREDICTION",
) -> list[UnpackedProductDesign]:
    """Unpack formulas into their full CAS-level substance composition.

    Each supplied formula is flattened into its constituent substances, with
    their amounts, CAS information, and SDS / regulatory details. One
    [`UnpackedProductDesign`][albert.resources.product_design.UnpackedProductDesign] is returned
    per input formula. Requests are automatically split into batches of 50
    inventory IDs, so large lists can be passed in a single call.

    !!! example
        ```python
        unpacked = client.product_design.get_unpacked_products(
            inventory_ids=["INVA9999999"],
            unpack_id="DESIGN",
        )
        substances = unpacked[0].cas_level_substances or []
        for substance in substances:
            print(substance.cas_id, substance.amount)
        ```

    Parameters
    ----------
    inventory_ids : list[InventoryId]
        The formula Inventory IDs to unpack (format ``INV...``, e.g. ``"INVA9999999"``).
    unpack_id : {"DESIGN", "PREDICTION"}, optional
        Which unpacking mode the server should use. Defaults to ``"PREDICTION"``.

    Returns
    -------
    list[UnpackedProductDesign]
        The unpacked composition, one entry per input formula.
    """
    url = f"{self.base_path}/{unpack_id}/unpack"
    batches = [inventory_ids[i : i + 50] for i in range(0, len(inventory_ids), 50)]
    return [
        UnpackedProductDesign(**item)
        for batch in batches
        for item in self.session.get(url, params={"formulaId": batch}).json()
    ]