Skip to content

Commit 796b544

Browse files
author
Callum Dickinson
committed
Add/fix missing/incorrect field definitions for records
* Add the missing `active` field to the `Product` record class. * Add the missing `sale_ok` field to the `Product` record class. * Fix the incorrect `default_code` field definition on the `Product` record class, by making it optional. * Add the missing `invoice_count` field to the `SaleOrder` record class. * Add the missing `invoice_ids` and `invoices` fields to the `SaleOrder` record class. * Add the missing `action_cancel` method to the `SaleOrder` record and manager class. * Fix a bug where new-style union type hints were not being handled by the parser, due to `typing.get_origin` returning a different origin type from the older `typing.Union` construct.
1 parent b1164c0 commit 796b544

File tree

7 files changed

+182
-8
lines changed

7 files changed

+182
-8
lines changed

changelog.d/12.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add/fix missing/incorrect field definitions for records

docs/managers/product.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,16 @@ The record class currently implements the following fields and methods.
254254
For more information on attributes and methods common to all record types,
255255
see [Record Attributes and Methods](index.md#attributes-and-methods).
256256

257+
### `active`
258+
259+
```python
260+
active: bool
261+
```
262+
263+
Whether or not this product is active (enabled).
264+
265+
*Added in version 0.2.0.*
266+
257267
### `categ_id`
258268

259269
```python
@@ -311,14 +321,15 @@ and caches it for subsequent accesses.
311321
### `default_code`
312322

313323
```python
314-
default_code: str
324+
default_code: str | Literal[False]
315325
```
316326

317-
The Default Code for this product.
327+
The Default Code for this product, if set.
318328

319329
In the OpenStack Integration add-on, this is used to store
320330
the rated unit for the service product.
321331

332+
*Changed in version 0.2.0*: Made `default_code` optional.
322333

323334
### `description`
324335

@@ -346,7 +357,6 @@ The list price of the product.
346357

347358
This becomes the unit price of the product on invoices.
348359

349-
350360
### `name`
351361

352362
```python
@@ -355,6 +365,16 @@ name: str
355365

356366
The name of the product.
357367

368+
### `sale_ok`
369+
370+
```python
371+
sale_ok: bool
372+
```
373+
374+
Whether or not this product is sellable.
375+
376+
*Added in version 0.2.0.*
377+
358378
### `uom_id`
359379

360380
```python

docs/managers/sale-order.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,39 @@ For more information on how to use managers, refer to [Managers](index.md).
3535

3636
The following manager methods are also available, in addition to the standard methods.
3737

38+
### `action_cancel`
39+
40+
```python
41+
action_cancel(
42+
sale_order: int | SaleOrder,
43+
) -> None
44+
```
45+
46+
Cancel the given sale order.
47+
48+
```python
49+
>>> from openstack_odooclient import Client as OdooClient
50+
>>> odoo_client = OdooClient(
51+
... hostname="localhost",
52+
... port=8069,
53+
... protocol="jsonrpc",
54+
... database="odoodb",
55+
... user="test-user",
56+
... password="<password>",
57+
... )
58+
>>> odoo_client.sale_orders.action_cancel(
59+
... sale_order=1234, # ID or object
60+
... )
61+
```
62+
63+
*Added in version 0.2.0.*
64+
65+
#### Parameters
66+
67+
| Name | Type | Description | Default |
68+
|--------------|-------------------|--------------------------|------------|
69+
| `sale_order` | `int | SaleOrder` | The sale order to cancel | (required) |
70+
3871
### `action_confirm`
3972

4073
```python
@@ -187,6 +220,39 @@ display_name: str
187220

188221
The display name of the sale order.
189222

223+
### `invoice_count`
224+
225+
```python
226+
invoice_count: int
227+
```
228+
229+
The number of [invoices (account moves)](account-move.md) generated from the sale order.
230+
231+
*Added in version 0.2.0.*
232+
233+
### `invoice_ids`
234+
235+
```python
236+
invoice_ids: list[int]
237+
```
238+
239+
A list of IDs for [invoices (account moves)](account-move.md) generated from the sale order.
240+
241+
*Added in version 0.2.0.*
242+
243+
### `invoices`
244+
245+
```python
246+
invoices: list[AccountMove]
247+
```
248+
249+
The [invoices (account moves)](account-move.md) generated from the sale order.
250+
251+
This fetches the full records from Odoo once,
252+
and caches them for subsequent accesses.
253+
254+
*Added in version 0.2.0.*
255+
190256
### `invoice_status`
191257

192258
```python
@@ -337,6 +403,30 @@ Values:
337403
* ``done`` - Finalised and settled sale order, cannot be modified
338404
* ``cancel`` - Cancelled sale order, can be deleted in most cases
339405

406+
### `action_cancel`
407+
408+
```python
409+
action_cancel() -> None
410+
```
411+
412+
Cancel this sale order.
413+
414+
```python
415+
>>> from openstack_odooclient import Client as OdooClient
416+
>>> odoo_client = OdooClient(
417+
... hostname="localhost",
418+
... port=8069,
419+
... protocol="jsonrpc",
420+
... database="odoodb",
421+
... user="test-user",
422+
... password="<password>",
423+
... )
424+
>>> sale_order = odoo_client.sale_orders.get(1234)
425+
>>> sale_order.action_cancel()
426+
```
427+
428+
*Added in version 0.2.0.*
429+
340430
### `action_confirm`
341431

342432
```python

openstack_odooclient/base/record.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
from dataclasses import dataclass
2121
from datetime import date, datetime
22-
from types import MappingProxyType
22+
from types import MappingProxyType, UnionType
2323
from typing import (
2424
TYPE_CHECKING,
2525
Annotated,
@@ -392,7 +392,8 @@ def _getattr_model_ref(
392392
# The following is for decoding a singular model ref value.
393393
# Check if the model ref is optional, and if it is,
394394
# return the desired value for when the value is empty.
395-
if get_type_origin(attr_type) is Union:
395+
attr_type_origin = get_type_origin(attr_type)
396+
if attr_type_origin is Union or attr_type_origin is UnionType:
396397
unsupported_union = (
397398
"Only unions of the format Optional[T], "
398399
"Union[T, type(None)] or Union[T, Literal[False]] "

openstack_odooclient/base/record_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ def get(
360360
:param optional: Return ``None`` if not found, defaults to ``False``
361361
:raises RecordNotFoundError: Record with the given ID not found
362362
:return: List of records
363-
:rtype: Record | list[str, Any]
363+
:rtype: Record | dict[str, Any]
364364
"""
365365
try:
366366
return self.list(

openstack_odooclient/managers/product.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727

2828

2929
class Product(RecordBase["ProductManager"]):
30+
active: bool
31+
"""Whether or not this product is active (enabled).
32+
33+
*Added in version 0.2.0.*
34+
"""
35+
3036
categ_id: Annotated[int, ModelRef("categ_id", ProductCategory)]
3137
"""The ID for the category this product is under."""
3238

@@ -53,11 +59,13 @@ class Product(RecordBase["ProductManager"]):
5359
and caches it for subsequent accesses.
5460
"""
5561

56-
default_code: str
57-
"""The Default Code for this product.
62+
default_code: str | Literal[False]
63+
"""The Default Code for this product, if set.
5864
5965
In the OpenStack Integration add-on, this is used to store
6066
the rated unit for the service product.
67+
68+
*Changed in version 0.2.0*: Made `default_code` optional.
6169
"""
6270

6371
description: str
@@ -75,6 +83,12 @@ class Product(RecordBase["ProductManager"]):
7583
name: str
7684
"""The name of the product."""
7785

86+
sale_ok: bool
87+
"""Whether or not this product is sellable.
88+
89+
*Added in version 0.2.0.*
90+
"""
91+
7892
uom_id: Annotated[int, ModelRef("uom_id", Uom)]
7993
"""The ID for the Unit of Measure for this product."""
8094

openstack_odooclient/managers/sale_order.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ class SaleOrder(RecordBase["SaleOrderManager"]):
5454
display_name: str
5555
"""The display name of the sale order."""
5656

57+
invoice_count: int
58+
"""The number of invoices generated from the sale order.
59+
60+
*Added in version 0.2.0.*
61+
"""
62+
63+
invoice_ids: Annotated[list[int], ModelRef("invoice_ids", AccountMove)]
64+
"""A list of IDs for invoices generated from the sale order.
65+
66+
*Added in version 0.2.0.*
67+
"""
68+
69+
invoices: Annotated[
70+
list[AccountMove],
71+
ModelRef("invoice_ids", AccountMove),
72+
]
73+
"""The invoices generated from the sale order.
74+
75+
This fetches the full records from Odoo once,
76+
and caches them for subsequent accesses.
77+
78+
*Added in version 0.2.0.*
79+
"""
80+
5781
invoice_status: Literal["no", "to invoice", "invoiced", "upselling"]
5882
"""The current invoicing status of this sale order.
5983
@@ -145,6 +169,13 @@ class SaleOrder(RecordBase["SaleOrderManager"]):
145169
* ``cancel`` - Cancelled sale order, can be deleted in most cases
146170
"""
147171

172+
def action_cancel(self) -> None:
173+
"""Cancel this sale order.
174+
175+
*Added in version 0.2.0.*
176+
"""
177+
self._env.action_cancel(self.id)
178+
148179
def action_confirm(self) -> None:
149180
"""Confirm this sale order."""
150181
self._env.action_confirm(self.id)
@@ -158,6 +189,22 @@ class SaleOrderManager(NamedRecordManagerBase[SaleOrder]):
158189
env_name = "sale.order"
159190
record_class = SaleOrder
160191

192+
def action_cancel(self, sale_order: int | SaleOrder) -> None:
193+
"""Cancel the given sale order.
194+
195+
*Added in version 0.2.0.*
196+
197+
:param sale_order: The sale order to cancel
198+
:type sale_order: int | SaleOrder
199+
"""
200+
self._env.action_cancel(
201+
(
202+
sale_order.id
203+
if isinstance(sale_order, SaleOrder)
204+
else sale_order
205+
),
206+
)
207+
161208
def action_confirm(self, sale_order: int | SaleOrder) -> None:
162209
"""Confirm the given sale order.
163210
@@ -188,6 +235,7 @@ def create_invoices(self, sale_order: int | SaleOrder) -> None:
188235

189236

190237
# NOTE(callumdickinson): Import here to avoid circular imports.
238+
from .account_move import AccountMove # noqa: E402
191239
from .currency import Currency # noqa: E402
192240
from .partner import Partner # noqa: E402
193241
from .project import Project # noqa: E402

0 commit comments

Comments
 (0)