Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/albert/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

__all__ = ["Albert", "AlbertClientCredentials", "AlbertSSOClient"]

__version__ = "1.11.0"
__version__ = "1.13.0b1"
6 changes: 6 additions & 0 deletions src/albert/resources/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from albert.resources.acls import ACL
from albert.resources.cas import Cas
from albert.resources.companies import Company
from albert.resources.lists import ListItem
from albert.resources.locations import Location
from albert.resources.tagged_base import BaseTaggedResource
from albert.resources.tags import Tag
Expand Down Expand Up @@ -75,6 +76,8 @@ class CasAmount(BaseAlbertModel):
The SMILES string of the CAS Number resource. Obtained from the Cas object when provided.
number: str | None
The CAS number. Obtained from the Cas object when provided.
inventory_function: list[ListItem | EntityLink | str] | None
Business-controlled functions associated with the CAS in this inventory context.

!!! tip
---
Expand All @@ -87,6 +90,9 @@ class CasAmount(BaseAlbertModel):
target: float | None = Field(default=None, alias="inventoryValue")
id: str | None = Field(default=None)
cas_category: str | None = Field(default=None, alias="casCategory")
inventory_function: list[SerializeAsEntityLink[ListItem] | str] | None = Field(
default=None, alias="inventoryFunction"
)
type: str | None = Field(default=None)
classification_type: str | None = Field(default=None, alias="classificationType")

Expand Down
3 changes: 2 additions & 1 deletion src/albert/resources/lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ class ListItem(BaseResource):
category : ListItemCategory | None
The category of the list item. Allowed values are `businessDefined`, `userDefined`, `projects`, and `extensions`.
list_type : str | None
The type of the list item. Allowed values are `projectState` for `projects` and `extensions` for `extensions`.
The type of the list item. Allowed values are `projectState` for `projects`, `extensions` for `extensions`,
and `casCategory` or `inventoryFunction` for `inventory`.
"""

name: str
Expand Down
71 changes: 71 additions & 0 deletions src/albert/utils/inventory.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from collections.abc import Iterable
from typing import Any

from albert.core.shared.models.base import BaseResource, EntityLink
from albert.resources.inventory import CasAmount


Expand Down Expand Up @@ -56,6 +57,61 @@ def _build_cas_delete_operation(identifier: str) -> dict[str, Any]:
}


def _normalize_inventory_function_ids(
value: list[BaseResource | EntityLink | str] | None,
) -> list[str]:
if not value:
return []
ids: list[str] = []
for item in value:
if isinstance(item, str):
if item:
ids.append(item)
continue
if isinstance(item, BaseResource):
if item.id:
ids.append(item.id)
continue
if isinstance(item, EntityLink):
if item.id:
ids.append(item.id)
continue
return ids


def _build_inventory_function_operations(
*,
entity_id: str,
existing: list[BaseResource | EntityLink | str] | None,
updated: list[BaseResource | EntityLink | str] | None,
) -> list[dict[str, Any]]:
existing_ids = set(_normalize_inventory_function_ids(existing))
updated_ids = set(_normalize_inventory_function_ids(updated))
to_add = sorted(updated_ids - existing_ids)
to_delete = sorted(existing_ids - updated_ids)

operations: list[dict[str, Any]] = []
if to_add:
operations.append(
{
"attribute": "inventoryFunction",
"entityId": entity_id,
"operation": "add",
"newValue": to_add,
}
)
if to_delete:
operations.append(
{
"attribute": "inventoryFunction",
"entityId": entity_id,
"operation": "delete",
"oldValue": to_delete,
}
)
return operations


def _build_cas_scalar_operation(
*,
attribute: str,
Expand Down Expand Up @@ -117,6 +173,14 @@ def _build_cas_update_operations(existing: CasAmount, updated: CasAmount) -> lis
if operation is not None:
operations.append(operation)

operations.extend(
_build_inventory_function_operations(
entity_id=identifier,
existing=existing.inventory_function,
updated=updated.inventory_function,
)
)

return operations


Expand Down Expand Up @@ -159,6 +223,13 @@ def _build_cas_patch_operations(
)
if target_operation is not None:
operations.append(target_operation)
operations.extend(
_build_inventory_function_operations(
entity_id=identifier,
existing=None,
updated=cas_amount.inventory_function,
)
)

removals = [existing_lookup[key] for key in existing_lookup.keys() - updated_lookup.keys()]
for cas_amount in removals:
Expand Down
1 change: 1 addition & 0 deletions tests/resources/test_inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def test_cas_amount_attributes():
"target",
"id",
"cas_category",
"inventory_function",
"created",
"updated",
"classification_type",
Expand Down