layrz-sdk 4.0.23__py3-none-any.whl → 4.1.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. layrz_sdk/decorators/func_timing.py +14 -7
  2. layrz_sdk/entities/__init__.py +7 -0
  3. layrz_sdk/entities/action.py +28 -16
  4. layrz_sdk/entities/action_geofence_ownership.py +0 -2
  5. layrz_sdk/entities/action_kind.py +0 -2
  6. layrz_sdk/entities/action_subkind.py +0 -2
  7. layrz_sdk/entities/asset.py +15 -9
  8. layrz_sdk/entities/asset_constants.py +10 -9
  9. layrz_sdk/entities/asset_contact.py +7 -3
  10. layrz_sdk/entities/asset_operation_mode.py +0 -2
  11. layrz_sdk/entities/ats_entry.py +11 -4
  12. layrz_sdk/entities/ats_exit_history.py +21 -19
  13. layrz_sdk/entities/ats_operation.py +57 -17
  14. layrz_sdk/entities/ats_possible_entry.py +9 -4
  15. layrz_sdk/entities/ats_possible_exit.py +19 -9
  16. layrz_sdk/entities/ats_purchaseorder.py +53 -12
  17. layrz_sdk/entities/ats_reception.py +16 -4
  18. layrz_sdk/entities/broadcast/payload.py +40 -8
  19. layrz_sdk/entities/broadcast/result.py +21 -2
  20. layrz_sdk/entities/broadcast/service.py +12 -2
  21. layrz_sdk/entities/case.py +34 -7
  22. layrz_sdk/entities/charts/axis_config.py +13 -5
  23. layrz_sdk/entities/charts/bar_chart.py +12 -1
  24. layrz_sdk/entities/charts/chart_data_serie.py +17 -1
  25. layrz_sdk/entities/charts/column_chart.py +12 -1
  26. layrz_sdk/entities/charts/html_chart.py +8 -4
  27. layrz_sdk/entities/charts/line_chart.py +12 -3
  28. layrz_sdk/entities/charts/map_chart.py +14 -5
  29. layrz_sdk/entities/charts/map_point.py +7 -1
  30. layrz_sdk/entities/charts/number_chart.py +8 -4
  31. layrz_sdk/entities/charts/pie_chart.py +11 -3
  32. layrz_sdk/entities/charts/radar_chart.py +11 -3
  33. layrz_sdk/entities/charts/radial_bar_chart.py +11 -3
  34. layrz_sdk/entities/charts/scatter_chart.py +12 -3
  35. layrz_sdk/entities/charts/scatter_serie.py +11 -1
  36. layrz_sdk/entities/charts/scatter_serie_item.py +7 -1
  37. layrz_sdk/entities/charts/table_chart.py +7 -3
  38. layrz_sdk/entities/charts/table_header.py +7 -1
  39. layrz_sdk/entities/charts/table_row.py +7 -1
  40. layrz_sdk/entities/charts/timeline_chart.py +11 -3
  41. layrz_sdk/entities/charts/timeline_serie.py +7 -1
  42. layrz_sdk/entities/charts/timeline_serie_item.py +7 -1
  43. layrz_sdk/entities/checkpoint.py +20 -13
  44. layrz_sdk/entities/command_series_ticket.py +29 -4
  45. layrz_sdk/entities/comment.py +15 -4
  46. layrz_sdk/entities/custom_field.py +12 -4
  47. layrz_sdk/entities/custom_report_page.py +3 -0
  48. layrz_sdk/entities/destination_phone.py +7 -1
  49. layrz_sdk/entities/device.py +11 -4
  50. layrz_sdk/entities/event.py +20 -4
  51. layrz_sdk/entities/exchange_service.py +12 -4
  52. layrz_sdk/entities/function.py +11 -4
  53. layrz_sdk/entities/geofence.py +12 -4
  54. layrz_sdk/entities/geofence_category.py +0 -2
  55. layrz_sdk/entities/last_message.py +7 -3
  56. layrz_sdk/entities/locator.py +95 -0
  57. layrz_sdk/entities/message.py +16 -9
  58. layrz_sdk/entities/modbus/config.py +7 -1
  59. layrz_sdk/entities/modbus/parameter.py +7 -1
  60. layrz_sdk/entities/modbus/wait.py +11 -1
  61. layrz_sdk/entities/notification_type.py +0 -2
  62. layrz_sdk/entities/operation.py +37 -16
  63. layrz_sdk/entities/operation_case_payload.py +39 -13
  64. layrz_sdk/entities/operation_payload.py +63 -26
  65. layrz_sdk/entities/operation_type.py +0 -2
  66. layrz_sdk/entities/outbound_service.py +11 -4
  67. layrz_sdk/entities/parameter_update.py +25 -0
  68. layrz_sdk/entities/platform.py +0 -2
  69. layrz_sdk/entities/position.py +7 -3
  70. layrz_sdk/entities/preset.py +15 -9
  71. layrz_sdk/entities/report.py +9 -5
  72. layrz_sdk/entities/report_col.py +17 -3
  73. layrz_sdk/entities/report_configuration.py +7 -1
  74. layrz_sdk/entities/report_data_type.py +1 -3
  75. layrz_sdk/entities/report_format.py +1 -5
  76. layrz_sdk/entities/report_header.py +12 -29
  77. layrz_sdk/entities/report_page.py +7 -3
  78. layrz_sdk/entities/report_row.py +7 -19
  79. layrz_sdk/entities/request_type.py +0 -2
  80. layrz_sdk/entities/sensor.py +11 -4
  81. layrz_sdk/entities/sensor_mask.py +16 -5
  82. layrz_sdk/entities/sound_effect.py +0 -2
  83. layrz_sdk/entities/static_position.py +6 -1
  84. layrz_sdk/entities/telemetry/assetmessage.py +14 -15
  85. layrz_sdk/entities/telemetry/devicemessage.py +19 -9
  86. layrz_sdk/entities/text_alignment.py +0 -2
  87. layrz_sdk/entities/timezone.py +12 -4
  88. layrz_sdk/entities/trigger.py +46 -13
  89. layrz_sdk/entities/trigger_kind.py +1 -5
  90. layrz_sdk/entities/user.py +11 -4
  91. layrz_sdk/entities/waypoint.py +38 -16
  92. layrz_sdk/entities/weekday.py +1 -3
  93. layrz_sdk/helpers/color.py +1 -6
  94. layrz_sdk/lcl/core.py +0 -1
  95. {layrz_sdk-4.0.23.dist-info → layrz_sdk-4.1.8.dist-info}/METADATA +2 -2
  96. layrz_sdk-4.1.8.dist-info/RECORD +123 -0
  97. layrz_sdk-4.0.23.dist-info/RECORD +0 -121
  98. {layrz_sdk-4.0.23.dist-info → layrz_sdk-4.1.8.dist-info}/WHEEL +0 -0
  99. {layrz_sdk-4.0.23.dist-info → layrz_sdk-4.1.8.dist-info}/licenses/LICENSE +0 -0
  100. {layrz_sdk-4.0.23.dist-info → layrz_sdk-4.1.8.dist-info}/top_level.txt +0 -0
@@ -3,7 +3,7 @@
3
3
  import asyncio
4
4
  import logging
5
5
  import os
6
- from collections.abc import Callable
6
+ from collections.abc import Callable, Coroutine
7
7
  from functools import wraps
8
8
  from typing import Any, ParamSpec, TypeVar, overload
9
9
 
@@ -13,14 +13,21 @@ P = ParamSpec('P')
13
13
  log = logging.getLogger(__name__)
14
14
 
15
15
  SHOULD_DISPLAY = os.environ.get('LAYRZ_SDK_DISPLAY_TIMING', '1') == '1'
16
+ if raw_depth := os.environ.get('LAYRZ_SDK_TIMING_DEPTH'):
17
+ try:
18
+ MAX_DEPTH = int(raw_depth)
19
+ except ValueError:
20
+ MAX_DEPTH = 0
21
+ else:
22
+ MAX_DEPTH = 0
16
23
 
17
24
 
18
25
  @overload
19
- def func_timing(func: Callable[P, T]) -> Callable[P, T]: ...
26
+ def func_timing(func: Callable[P, T]) -> Callable[P, T | Coroutine[Any, Any, T]]: ...
20
27
 
21
28
 
22
29
  @overload
23
- def func_timing(*, depth: int) -> Callable[[Callable[P, T]], Callable[P, T]]: ...
30
+ def func_timing(*, depth: int) -> Callable[[Callable[P, T]], Callable[P, T | Coroutine[Any, Any, T]]]: ...
24
31
 
25
32
 
26
33
  def func_timing(
@@ -47,8 +54,8 @@ def func_timing(
47
54
  result: T = await func(*args, **kwargs) # type: ignore
48
55
  diff = time.perf_counter_ns() - start_time
49
56
 
50
- if SHOULD_DISPLAY:
51
- log.info(f'{prefix}{func.__name__}() took {_readable_time(diff)}')
57
+ if SHOULD_DISPLAY and depth <= MAX_DEPTH:
58
+ log.info(f'{prefix}{func.__name__}() took {_readable_time(diff)}') # ty: ignore
52
59
 
53
60
  return result
54
61
 
@@ -58,8 +65,8 @@ def func_timing(
58
65
  result = func(*args, **kwargs)
59
66
  diff = time.perf_counter_ns() - start_time
60
67
 
61
- if SHOULD_DISPLAY:
62
- log.info(f'{prefix}{func.__name__}() took {_readable_time(diff)}')
68
+ if SHOULD_DISPLAY and depth <= MAX_DEPTH:
69
+ log.info(f'{prefix}{func.__name__}() took {_readable_time(diff)}') # ty: ignore
63
70
 
64
71
  return result
65
72
 
@@ -68,6 +68,7 @@ from .function import Function
68
68
  from .geofence import Geofence
69
69
  from .geofence_category import GeofenceCategory
70
70
  from .last_message import LastMessage
71
+ from .locator import Locator, LocatorMqttConfig
71
72
  from .message import Message
72
73
  from .modbus import ModbusConfig, ModbusParameter, ModbusSchema, ModbusStatus, ModbusWait
73
74
  from .notification_type import TwilioNotificationType
@@ -76,6 +77,7 @@ from .operation_case_payload import OperationCaseCommentPayload, OperationCasePa
76
77
  from .operation_payload import OperationPayload
77
78
  from .operation_type import OperationType
78
79
  from .outbound_service import OutboundService
80
+ from .parameter_update import ParameterUpdate
79
81
  from .platform import Platform
80
82
  from .position import Position
81
83
  from .presence_type import PresenceType
@@ -92,6 +94,7 @@ from .request_type import HttpRequestType
92
94
  from .sensor import Sensor
93
95
  from .sensor_mask import SensorMask
94
96
  from .sound_effect import SoundEffect
97
+ from .static_position import StaticPosition
95
98
  from .telemetry import AssetMessage, DeviceMessage
96
99
  from .text_alignment import TextAlignment
97
100
  from .timezone import Timezone
@@ -155,6 +158,8 @@ __all__ = [
155
158
  'HttpRequestType',
156
159
  'LastMessage',
157
160
  'LineChart',
161
+ 'Locator',
162
+ 'LocatorMqttConfig',
158
163
  'MapCenterType',
159
164
  'MapChart',
160
165
  'MapPoint',
@@ -192,6 +197,7 @@ __all__ = [
192
197
  'Sensor',
193
198
  'SensorMask',
194
199
  'SoundEffect',
200
+ 'StaticPosition',
195
201
  'TableChart',
196
202
  'TableHeader',
197
203
  'TableRow',
@@ -218,4 +224,5 @@ __all__ = [
218
224
  'OrderStatus',
219
225
  'AtsOperationMovement',
220
226
  'AtsOperation',
227
+ 'ParameterUpdate',
221
228
  ]
@@ -1,8 +1,4 @@
1
- """Action entity"""
2
-
3
- from datetime import timedelta
4
-
5
- from pydantic import BaseModel, Field
1
+ from pydantic import BaseModel, ConfigDict, Field, field_serializer
6
2
 
7
3
  from .action_geofence_ownership import ActionGeofenceOwnership
8
4
  from .action_kind import ActionKind
@@ -13,20 +9,24 @@ from .geofence_category import GeofenceCategory
13
9
  class Action(BaseModel):
14
10
  """Action entity"""
15
11
 
16
- model_config = {
17
- 'json_encoders': {
18
- timedelta: lambda v: v.total_seconds(),
19
- ActionKind: lambda v: v.value,
20
- ActionSubKind: lambda v: v.value,
21
- GeofenceCategory: lambda v: v.value,
22
- ActionGeofenceOwnership: lambda v: v.value,
23
- },
24
- }
25
-
26
- pk: int = Field(..., description='Primary key of the action entity', alias='id')
12
+ model_config = ConfigDict(
13
+ validate_by_name=False,
14
+ validate_by_alias=True,
15
+ serialize_by_alias=True,
16
+ )
17
+
18
+ pk: int = Field(
19
+ ...,
20
+ description='Primary key of the action entity',
21
+ alias='id',
22
+ )
27
23
  name: str = Field(..., description='Name of the action')
28
24
  kind: ActionKind = Field(..., description='Kind of the action')
29
25
 
26
+ @field_serializer('kind', when_used='always')
27
+ def serialize_kind(self, kind: ActionKind) -> str:
28
+ return kind.value
29
+
30
30
  command_id: int | None = Field(
31
31
  default=None,
32
32
  description='Tag ID associated with the action to send commands to primary devices',
@@ -34,6 +34,10 @@ class Action(BaseModel):
34
34
 
35
35
  subkind: ActionSubKind = Field(default=ActionSubKind.UNUSED, description='Subkind of the action')
36
36
 
37
+ @field_serializer('subkind', when_used='always')
38
+ def serialize_subkind(self, subkind: ActionSubKind) -> str:
39
+ return subkind.value
40
+
37
41
  wait_for_image: bool = Field(
38
42
  default=False,
39
43
  description='Whether to wait for an image to be taken before executing the action',
@@ -45,6 +49,10 @@ class Action(BaseModel):
45
49
  description='Geofence category of the action',
46
50
  )
47
51
 
52
+ @field_serializer('geofence_cateogry', when_used='always')
53
+ def serialize_geofence_category(self, geofence_category: GeofenceCategory) -> str:
54
+ return geofence_category.value
55
+
48
56
  geofence_name_formula: str | None = Field(
49
57
  default=None,
50
58
  description='Formula to generate the geofence name',
@@ -67,4 +75,8 @@ class Action(BaseModel):
67
75
  description='Ownership of the new geofence created by the action',
68
76
  )
69
77
 
78
+ @field_serializer('new_geofence_ownership', when_used='always')
79
+ def serialize_new_geofence_ownership(self, ownership: ActionGeofenceOwnership) -> str:
80
+ return ownership.value
81
+
70
82
  owner_id: int | None = Field(default=None, description='Owner ID')
@@ -1,5 +1,3 @@
1
- """Action geofence ownership"""
2
-
3
1
  from enum import StrEnum
4
2
  from typing import Self
5
3
 
@@ -1,5 +1,3 @@
1
- """Action kind"""
2
-
3
1
  from enum import StrEnum
4
2
  from typing import Self
5
3
 
@@ -1,5 +1,3 @@
1
- """Action sub kind"""
2
-
3
1
  from enum import StrEnum
4
2
  from typing import Self
5
3
 
@@ -1,8 +1,6 @@
1
- """Asset Entity"""
2
-
3
1
  from typing import Any, Self
4
2
 
5
- from pydantic import BaseModel, Field, field_validator, model_validator
3
+ from pydantic import BaseModel, ConfigDict, Field, field_serializer, field_validator, model_validator
6
4
 
7
5
  from .asset_contact import AssetContact
8
6
  from .asset_operation_mode import AssetOperationMode
@@ -15,13 +13,16 @@ from .static_position import StaticPosition
15
13
  class Asset(BaseModel):
16
14
  """Asset entity definition"""
17
15
 
18
- model_config = {
19
- 'json_encoders': {
20
- AssetOperationMode: lambda v: v.value,
21
- }
22
- }
16
+ model_config = ConfigDict(
17
+ validate_by_name=False,
18
+ validate_by_alias=True,
19
+ serialize_by_alias=True,
20
+ )
23
21
 
24
- pk: int = Field(description='Defines the primary key of the asset', alias='id')
22
+ pk: int = Field(
23
+ description='Defines the primary key of the asset',
24
+ alias='id',
25
+ )
25
26
  name: str = Field(description='Defines the name of the asset')
26
27
  vin: str | None = Field(
27
28
  default=None,
@@ -30,6 +31,11 @@ class Asset(BaseModel):
30
31
  plate: str | None = Field(default=None, description='Defines the plate number of the asset')
31
32
  kind_id: int | None = Field(description='Defines the type of the asset', default=None)
32
33
  operation_mode: AssetOperationMode = Field(description='Defines the operation mode of the asset')
34
+
35
+ @field_serializer('operation_mode', when_used='always')
36
+ def serialize_operation_mode(self, operation_mode: AssetOperationMode) -> str:
37
+ return operation_mode.value
38
+
33
39
  sensors: list[Sensor] = Field(default_factory=list, description='Defines the list of sensors of the asset')
34
40
  custom_fields: list[CustomField] = Field(
35
41
  default_factory=list, description='Defines the list of custom fields of the asset'
@@ -1,22 +1,23 @@
1
- """Asset constants"""
2
-
3
1
  from datetime import timedelta
4
2
 
5
- from pydantic import BaseModel, Field
3
+ from pydantic import BaseModel, ConfigDict, Field, field_serializer
6
4
 
7
5
 
8
6
  class AssetConstants(BaseModel):
9
7
  """Asset constants"""
10
8
 
11
- model_config = {
12
- 'json_encoders': {
13
- timedelta: lambda v: v.total_seconds(),
14
- },
15
- }
16
-
9
+ model_config = ConfigDict(
10
+ validate_by_name=False,
11
+ validate_by_alias=True,
12
+ serialize_by_alias=True,
13
+ )
17
14
  distance_traveled: float = Field(default=0.0, description='Total distance traveled by the asset in meters')
18
15
  primary_device: str = Field(default='N/A', description='Primary device associated with the asset')
19
16
  elapsed_time: timedelta = Field(
20
17
  default=timedelta(seconds=0),
21
18
  description='Total elapsed time for the asset in seconds',
22
19
  )
20
+
21
+ @field_serializer('elapsed_time', when_used='always')
22
+ def serialize_elapsed_time(self, elapsed_time: timedelta) -> float:
23
+ return elapsed_time.total_seconds()
@@ -1,11 +1,15 @@
1
- """Asset contact information"""
2
-
3
- from pydantic import BaseModel, Field
1
+ from pydantic import BaseModel, ConfigDict, Field
4
2
 
5
3
 
6
4
  class AssetContact(BaseModel):
7
5
  """Asset contact information"""
8
6
 
7
+ model_config = ConfigDict(
8
+ validate_by_name=False,
9
+ validate_by_alias=True,
10
+ serialize_by_alias=True,
11
+ )
12
+
9
13
  name: str = Field(default='', description='Name of the contact person for the asset')
10
14
  phone: str = Field(default='', description='Phone number of the contact person for the asset')
11
15
  email: str = Field(default='', description='Email address of the contact person for the asset')
@@ -1,5 +1,3 @@
1
- """Asset Operation Mode"""
2
-
3
1
  from enum import StrEnum
4
2
  from typing import Self
5
3
 
@@ -1,12 +1,19 @@
1
- """Entry entity"""
2
-
3
- from pydantic import BaseModel, Field
1
+ from pydantic import BaseModel, ConfigDict, Field
4
2
 
5
3
 
6
4
  class AtsEntry(BaseModel):
7
5
  """Entry entity"""
8
6
 
9
- pk: int = Field(description='Defines the primary key of the Function', alias='id')
7
+ model_config = ConfigDict(
8
+ validate_by_name=False,
9
+ validate_by_alias=True,
10
+ serialize_by_alias=True,
11
+ )
12
+
13
+ pk: int = Field(
14
+ description='Defines the primary key of the Function',
15
+ alias='id',
16
+ )
10
17
  old_tank_level: float = Field(description='Old tank level in liters', default=0.0)
11
18
  new_tank_level: float = Field(description='New tank level in liters', default=0.0)
12
19
  density: float | None = Field(description='Density of the fuel in kg/m3', default=None)
@@ -1,30 +1,24 @@
1
- """Exit Execution History"""
2
-
3
1
  from datetime import datetime
4
2
  from typing import Literal
5
3
 
6
- from pydantic import (
7
- BaseModel,
8
- ConfigDict,
9
- Field,
10
- )
4
+ from pydantic import BaseModel, ConfigDict, Field, field_serializer
11
5
 
12
6
 
13
7
  class AtsExitExecutionHistory(BaseModel):
14
- model_config = {
15
- 'json_encoders': {
16
- datetime: lambda v: v.timestamp(),
17
- }
18
- }
19
- pk: int = Field(description='Primary key of the Exit Execution History', alias='id')
20
-
21
- from_asset_id: int = Field(
22
- description='ID of the asset from which the exit is initiated',
8
+ model_config = ConfigDict(
9
+ validate_by_name=False,
10
+ validate_by_alias=True,
11
+ serialize_by_alias=True,
12
+ from_attributes=True,
23
13
  )
24
- to_asset_id: int = Field(
25
- description='ID of the asset to which the exit is directed',
14
+ pk: int = Field(
15
+ description='Primary key of the Exit Execution History',
16
+ alias='id',
26
17
  )
27
18
 
19
+ from_asset_id: int = Field(description='ID of the asset from which the exit is initiated')
20
+ to_asset_id: int = Field(description='ID of the asset to which the exit is directed')
21
+
28
22
  status: Literal['PENDING', 'FAILED', 'SUCCESS'] = Field(default='PENDING')
29
23
 
30
24
  from_app: Literal['ATSWEB', 'ATSMOBILE', 'NFC'] | None = Field(
@@ -38,5 +32,13 @@ class AtsExitExecutionHistory(BaseModel):
38
32
  to_asset_mileage: float | None = Field(default=None, description='Mileage of the asset to which the exit is directed')
39
33
 
40
34
  created_at: datetime = Field(description='Timestamp when the exit was created')
35
+
36
+ @field_serializer('created_at', when_used='always')
37
+ def serialize_created_at(self, created_at: datetime) -> float:
38
+ return created_at.timestamp()
39
+
41
40
  updated_at: datetime = Field(description='Timestamp when the exit was last updated')
42
- model_config = ConfigDict(from_attributes=True)
41
+
42
+ @field_serializer('updated_at', when_used='always')
43
+ def serialize_updated_at(self, updated_at: datetime) -> float:
44
+ return updated_at.timestamp()
@@ -3,7 +3,7 @@
3
3
  from datetime import datetime
4
4
  from enum import StrEnum
5
5
 
6
- from pydantic import BaseModel, Field
6
+ from pydantic import BaseModel, ConfigDict, Field, field_serializer
7
7
 
8
8
  from .ats_purchaseorder import AtsPurchaseOrder, DeliveryCategories, OrderCategories, OrderStatus
9
9
 
@@ -11,15 +11,29 @@ from .ats_purchaseorder import AtsPurchaseOrder, DeliveryCategories, OrderCatego
11
11
  class AtsOperationMovement(BaseModel):
12
12
  """Ats operation movement entity"""
13
13
 
14
- model_config = {
15
- 'json_encoders': {
16
- datetime: lambda v: v.timestamp(),
17
- OrderStatus: lambda v: v.value,
18
- },
19
- }
20
- pk: int | None = Field(description='Defines the primary key of the Function', alias='id', default=None)
14
+ model_config = ConfigDict(
15
+ validate_by_name=False,
16
+ validate_by_alias=True,
17
+ serialize_by_alias=True,
18
+ )
19
+
20
+ pk: int | None = Field(
21
+ description='Defines the primary key of the Function',
22
+ default=None,
23
+ alias='id',
24
+ )
21
25
  status: OrderStatus | None = Field(description='Current status of the order', default=None)
26
+
27
+ @field_serializer('status', when_used='always')
28
+ def serialize_status(self, status: OrderStatus | None) -> str | None:
29
+ return status.value if status else None
30
+
22
31
  created_at: datetime | None = Field(description='Timestamp when the operation movement was created', default=None)
32
+
33
+ @field_serializer('created_at', when_used='always')
34
+ def serialize_created_at(self, created_at: datetime | None) -> float | None:
35
+ return created_at.timestamp() if created_at else None
36
+
23
37
  asset_id: int | None = Field(description='ID of the asset', default=None)
24
38
  operation_id: int | None = Field(description='ID of the operation', default=None)
25
39
 
@@ -27,21 +41,47 @@ class AtsOperationMovement(BaseModel):
27
41
  class AtsOperation(BaseModel):
28
42
  """Entry entity"""
29
43
 
30
- model_config = {
31
- 'json_encoders': {
32
- datetime: lambda v: v.timestamp(),
33
- OrderStatus: lambda v: v.value,
34
- OrderCategories: lambda v: v.value,
35
- DeliveryCategories: lambda v: v.value,
36
- },
37
- }
38
- pk: int = Field(description='Defines the primary key of the Function', alias='id')
44
+ model_config = ConfigDict(
45
+ validate_by_name=False,
46
+ validate_by_alias=True,
47
+ serialize_by_alias=True,
48
+ )
49
+
50
+ pk: int = Field(
51
+ description='Defines the primary key of the Function',
52
+ alias='id',
53
+ )
39
54
  purchased_at: datetime = Field(description='Timestamp when the operation was purchased')
55
+
56
+ @field_serializer('purchased_at', when_used='always')
57
+ def serialize_purchased_at(self, purchased_at: datetime) -> float:
58
+ return purchased_at.timestamp()
59
+
40
60
  order_status: OrderStatus = Field(..., description='Current status of the order')
61
+
62
+ @field_serializer('order_status', when_used='always')
63
+ def serialize_order_status(self, order_status: OrderStatus) -> str:
64
+ return order_status.value
65
+
41
66
  category: OrderCategories = Field(..., description='Category of the operation')
67
+
68
+ @field_serializer('category', when_used='always')
69
+ def serialize_category(self, category: OrderCategories) -> str:
70
+ return category.value
71
+
42
72
  deliver_category: DeliveryCategories = Field(..., description='Delivery category of the operation')
73
+
74
+ @field_serializer('deliver_category', when_used='always')
75
+ def serialize_deliver_category(self, deliver_category: DeliveryCategories) -> str:
76
+ return deliver_category.value
77
+
43
78
  seller_asset_id: int = Field(description='ID of the seller asset')
44
79
  transport_asset_id: int = Field(description='ID of the transport asset')
45
80
  finished_at: datetime | None = Field(description='Timestamp when the operation was finished', default=None)
81
+
82
+ @field_serializer('finished_at', when_used='always')
83
+ def serialize_finished_at(self, finished_at: datetime | None) -> float | None:
84
+ return finished_at.timestamp() if finished_at else None
85
+
46
86
  history: list[AtsOperationMovement] = Field(description='List of operation movements')
47
87
  purchase_orders: list[AtsPurchaseOrder] = Field(description='List of purchase orders')
@@ -1,13 +1,17 @@
1
- """Entry entity"""
2
-
3
1
  from datetime import datetime
4
2
 
5
- from pydantic import BaseModel, Field
3
+ from pydantic import BaseModel, ConfigDict, Field
6
4
 
7
5
 
8
6
  class AtsPossibleEntry(BaseModel):
9
7
  """Entry entity"""
10
8
 
9
+ model_config = ConfigDict(
10
+ validate_by_name=False,
11
+ validate_by_alias=True,
12
+ serialize_by_alias=True,
13
+ )
14
+
11
15
  initial_tank_level: float = Field(description='Initial tank level in liters', default=0.0)
12
16
  tank_accumulator: float = Field(description='Tank accumulator in liters', default=0.0)
13
17
  is_ready: bool = Field(description='Indicates if the entry is ready', default=False)
@@ -20,7 +24,8 @@ class AtsPossibleEntry(BaseModel):
20
24
  is_recalculated: bool = Field(description='Indicates if the entry is recalculated', default=False)
21
25
  is_blackbox: bool = Field(description='Indicates if the entry is a black box', default=False)
22
26
  is_executed_by_command: bool | None = Field(
23
- description='Indicates if the entry is executed by command', default=False
27
+ description='Indicates if the entry is executed by command',
28
+ default=False,
24
29
  )
25
30
  is_ready_by_reception: bool | None = Field(description='Indicates if the entry is ready by reception', default=False)
26
31
  false_positive_count: int = Field(description='Count of false positives for the entry', default=0)
@@ -1,20 +1,21 @@
1
- """Ats Exit entity"""
2
-
3
1
  from datetime import datetime
4
2
 
5
- from pydantic import BaseModel, Field
3
+ from pydantic import BaseModel, ConfigDict, Field, field_serializer
6
4
 
7
5
 
8
6
  class AtsPossibleExit(BaseModel):
9
7
  """AtsPossibleExit entity"""
10
8
 
11
- model_config = {
12
- 'json_encoders': {
13
- datetime: lambda v: v.timestamp(),
14
- }
15
- }
9
+ model_config = ConfigDict(
10
+ validate_by_name=False,
11
+ validate_by_alias=True,
12
+ serialize_by_alias=True,
13
+ )
16
14
 
17
- pk: int = Field(description='Defines the primary key of the AtsPossibleExit', alias='id')
15
+ pk: int = Field(
16
+ description='Defines the primary key of the AtsPossibleExit',
17
+ alias='id',
18
+ )
18
19
 
19
20
  identifier: int | None = Field(
20
21
  default=None,
@@ -54,11 +55,20 @@ class AtsPossibleExit(BaseModel):
54
55
  default_factory=datetime.now,
55
56
  description='Timestamp when the exit started',
56
57
  )
58
+
59
+ @field_serializer('start_at', when_used='always')
60
+ def serialize_start_at(self, start_at: datetime) -> float:
61
+ return start_at.timestamp()
62
+
57
63
  end_at: datetime | None = Field(
58
64
  default=None,
59
65
  description='Timestamp when the exit ended',
60
66
  )
61
67
 
68
+ @field_serializer('end_at', when_used='always')
69
+ def serialize_end_at(self, end_at: datetime | None) -> float | None:
70
+ return end_at.timestamp() if end_at else None
71
+
62
72
  # Derived / bookkeeping flags
63
73
  is_recalculated: bool = Field(
64
74
  default=False,
@@ -1,9 +1,10 @@
1
- """Entry entity"""
2
-
3
1
  from datetime import datetime
4
2
  from enum import StrEnum
3
+ from typing import Any
4
+
5
+ from pydantic import BaseModel, ConfigDict, Field, field_serializer
5
6
 
6
- from pydantic import BaseModel, Field
7
+ from .asset import Asset
7
8
 
8
9
 
9
10
  class OrderStatus(StrEnum):
@@ -41,25 +42,65 @@ class DeliveryCategories(StrEnum):
41
42
  class AtsPurchaseOrder(BaseModel):
42
43
  """Entry entity"""
43
44
 
44
- model_config = {
45
- 'json_encoders': {
46
- datetime: lambda v: v.timestamp(),
47
- OrderStatus: lambda v: v.value,
48
- OrderCategories: lambda v: v.value,
49
- DeliveryCategories: lambda v: v.value,
50
- },
51
- }
52
- pk: int = Field(description='Defines the primary key of the Function', alias='id')
45
+ model_config = ConfigDict(
46
+ validate_by_name=False,
47
+ validate_by_alias=True,
48
+ serialize_by_alias=True,
49
+ )
50
+ pk: int = Field(
51
+ description='Defines the primary key of the Function',
52
+ alias='id',
53
+ )
53
54
  purchased_at: datetime = Field(description='Timestamp when the operation was purchased')
55
+
56
+ @field_serializer('purchased_at', when_used='always')
57
+ def serialize_purchased_at(self, purchased_at: datetime) -> float:
58
+ return purchased_at.timestamp()
59
+
54
60
  order_status: OrderStatus = Field(..., description='Current status of the order')
61
+
62
+ @field_serializer('order_status', when_used='always')
63
+ def serialize_order_status(self, order_status: OrderStatus) -> str:
64
+ return order_status.value
65
+
55
66
  order_id: int = Field(description='ID of the order')
56
67
  category: OrderCategories | None = Field(description='Category of the operation', default=None)
68
+
69
+ @field_serializer('category', when_used='always')
70
+ def serialize_category(self, category: OrderCategories | None) -> str | None:
71
+ return category.value if category else None
72
+
57
73
  deliver_category: DeliveryCategories | None = Field(description='Delivery category of the operation', default=None)
74
+
75
+ @field_serializer('deliver_category', when_used='always')
76
+ def serialize_deliver_category(self, deliver_category: DeliveryCategories | None) -> str | None:
77
+ return deliver_category.value if deliver_category else None
78
+
58
79
  seller_asset_id: int = Field(description='ID of the seller asset')
59
80
  transport_asset_id: int | None = Field(description='ID of the transport asset', default=None)
60
81
  asset_id: int = Field(description='ID of the asset')
82
+
83
+ seller_asset: Asset | None = Field(description='Seller asset details', default=None)
84
+ transport_asset: Asset | None = Field(description='Transport asset details', default=None)
85
+ asset: Asset | None = Field(description='Destination asset details', default=None)
61
86
  delivered_at: datetime | None = Field(description='Timestamp when the operation was delivered', default=None)
87
+
88
+ @field_serializer('delivered_at', when_used='always')
89
+ def serialize_delivered_at(self, delivered_at: datetime | None) -> float | None:
90
+ return delivered_at.timestamp() if delivered_at else None
91
+
62
92
  eta: datetime | None = Field(description='Estimated time of arrival to the destination', default=None)
93
+
94
+ @field_serializer('eta', when_used='always')
95
+ def serialize_eta(self, eta: datetime | None) -> float | None:
96
+ return eta.timestamp() if eta else None
97
+
63
98
  eta_updated_at: datetime | None = Field(description='Timestamp when the ETA was last updated', default=None)
99
+
100
+ @field_serializer('eta_updated_at', when_used='always')
101
+ def serialize_eta_updated_at(self, eta_updated_at: datetime | None) -> float | None:
102
+ return eta_updated_at.timestamp() if eta_updated_at else None
103
+
64
104
  invoice_type: str = Field(description='Type of the invoice')
65
105
  operation_id: int | None = Field(description='ID of the operation', default=None)
106
+ products_information: list[dict[str, Any]] = Field(description='List of products information', default_factory=list)