diff --git a/changelog.d/8.added.md b/changelog.d/8.added.md new file mode 100644 index 0000000..f2e5008 --- /dev/null +++ b/changelog.d/8.added.md @@ -0,0 +1 @@ +Add support for updating records diff --git a/docs/managers/account-move.md b/docs/managers/account-move.md index 893fca5..3e2ac57 100644 --- a/docs/managers/account-move.md +++ b/docs/managers/account-move.md @@ -265,7 +265,7 @@ Values: * ``reversed`` - Reversed * ``invoicing_legacy`` - Invoicing App Legacy -### state +### `state` ```python state: Literal["draft", "posted", "cancel"] diff --git a/docs/managers/index.md b/docs/managers/index.md index 8a58686..f0fb759 100644 --- a/docs/managers/index.md +++ b/docs/managers/index.md @@ -770,14 +770,55 @@ pass the returned IDs to the [``list``](#list) method. |-------------|--------------------------------------| | `list[int]` | The IDs of the newly created records | +### `update` + +```python +def update(record: int | Record, **fields: Any) -> None +``` + +Update one or more fields on this record in place. + +```python +>>> from openstack_odooclient import Client as OdooClient +>>> odoo_client = OdooClient( +... hostname="localhost", +... port=8069, +... protocol="jsonrpc", +... database="odoodb", +... user="test-user", +... password="", +... ) +>>> odoo_client.users.get(1234) +User(record={'id': 1234, 'name': 'Old Name', ...}, fields=None) +>>> odoo_client.users.update(1234, name="New Name") +>>> odoo_client.users.get(1234) +User(record={'id': 1234, 'name': 'New Name', ...}, fields=None) +``` + +Field names are passed as keyword arguments. +This method has the same flexibility with regards to what +field names are used as when [creating records](#create); +for example, when updating a model ref, either its ID +(e.g. ``user_id``) or object (e.g. ``user``) field names +can be used. + +*Added in version 0.2.0.* + +#### Parameters + +| Name | Type | Description | Default | +|------------|----------------|-----------------------------------------|------------| +| `record` | `int | Record` | The record to update (object or ID) | (required) | +| `**fields` | `Any` | Record field values (keyword arguments) | (required) | + ### `unlink`/`delete` ```python -unlink(*records: Record | int | Iterable[Record | int]) -> None +unlink(*records: int | Record | Iterable[int | Record]) -> None ``` ```python -delete(*records: Record | int | Iterable[Record | int]) -> None +delete(*records: int | Record | Iterable[int | Record]) -> None ``` Delete one or more records from Odoo. @@ -1357,6 +1398,44 @@ User(record={'id': 1234, ...}, fields=None) |------------------|-------------------| | `dict[str, Any]` | Record dictionary | +#### `update` + +```python +def update(**fields: Any) -> None +``` + +Update one or more fields on this record in place. + +```python +>>> user +User(record={'id': 1234, 'name': 'Old Name', ...}, fields=None) +>>> user.update(name="New Name") +>>> user.refresh() +User(record={'id': 1234, 'name': 'New Name', ...}, fields=None) +``` + +Field names are passed as keyword arguments. +This method has the same flexibility with regards to what +field names are used as when [creating records](#create); +for example, when updating a model ref, either its ID +(e.g. ``user_id``) or object (e.g. ``user``) field names +can be used. + +!!! note + + This record object is not updated in place by this method. + + If you need an updated version of the record object, + use the [`refresh`](#refresh) method to fetch the latest version. + +*Added in version 0.2.0.* + +##### Parameters + +| Name | Type | Description | Default | +|------------|-------|-----------------------------------------|------------| +| `**fields` | `Any` | Record field values (keyword arguments) | (required) | + #### `refresh` ```python @@ -1395,9 +1474,10 @@ Delete this record from Odoo. ```python >>> user -User(record={'id': 1234, 'name': 'Old Name', ...}, fields=None) +User(record={'id': 1234, ...}, fields=None) >>> user.unlink() >>> user.refresh() +Traceback (most recent call last): ... openstack_odooclient.exceptions.RecordNotFoundError: User record not found with ID: 1234 ``` diff --git a/openstack_odooclient/base/record.py b/openstack_odooclient/base/record.py index e650409..b97fa79 100644 --- a/openstack_odooclient/base/record.py +++ b/openstack_odooclient/base/record.py @@ -266,6 +266,23 @@ def as_dict(self, raw: bool = False) -> dict[str, Any]: } ) + def update(self, **fields: Any) -> None: + """Update one or more fields on this record in place. + + Field names are passed as keyword arguments. + This method has the same flexibility with regards to what + field names are used as when creating records; for example, + when updating a model ref, either its ID (e.g. ``user_id``) + or object (e.g. ``user``) field names can be used. + + Note that this record object is not updated in place by + this method. If you need an updated version of the record + object, use the `refresh` method to fetch the latest version. + + *Added in version 0.2.0.* + """ + self._manager.update(self.id, **fields) + def refresh(self) -> Self: """Fetch the latest version of this record from Odoo. diff --git a/openstack_odooclient/base/record_manager.py b/openstack_odooclient/base/record_manager.py index 123ec70..b2afded 100644 --- a/openstack_odooclient/base/record_manager.py +++ b/openstack_odooclient/base/record_manager.py @@ -629,7 +629,7 @@ def _encode_filter_field(self, field: str) -> tuple[Any, str]: type_hint = self._record_type_hints[local_field] return (type_hint, remote_field) - def create(self, **fields) -> int: + def create(self, **fields: Any) -> int: """Create a new record, using the specified keyword arguments as input fields. @@ -808,6 +808,25 @@ def _encode_create_field( self._encode_value(type_hint=type_hint, value=value), ) + def update(self, record: int | Record, **fields: Any) -> None: + """Update one or more fields on the given record in place. + + Field names are passed as keyword arguments. + This method has the same flexibility with regards to what + field names are used as when creating records; for example, + when updating a model ref, either its ID (e.g. ``user_id``) + or object (e.g. ``user``) field names can be used. + + *Added in version 0.2.0.* + + :param record: The record to update (object or ID) + :type record: int | Record + """ + self._env.update( + record.id if isinstance(record, RecordBase) else record, + self._encode_create_fields(fields), + ) + def unlink( self, *records: int | Record | Iterable[int | Record], diff --git a/pyproject.toml b/pyproject.toml index 0d8a202..d8a9394 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,6 +63,7 @@ packages = ["openstack_odooclient"] [tool.poe.tasks] lint = "ruff check" format = "ruff format" +type-check = "mypy openstack_odooclient" [tool.ruff] fix = true