Skip to content

Commit fa9d014

Browse files
jens-kuertenJens Kürten
andauthored
feat: Bom item field calculation (#41)
* feat: Add BOMItemFieldCalculationEvent and related data model * feat: Add part linking functionality to BOMItem class * fix: Ensure single items of target type are appended in get_items_of_type function * fix: update json schema * fix: Add part attribute to BOMItem documentation * feat: Add documents attribute to BOMItemFieldCalculationData and update documentation * fix: update schema json * add custom fields to bom item model * feat: Add cdb_object_id field to BOMItem model * update schema --------- Co-authored-by: Jens Kürten <jens.kuerten@contact-software.com>
1 parent 6d9c748 commit fa9d014

File tree

8 files changed

+2147
-0
lines changed

8 files changed

+2147
-0
lines changed

csfunctions/events/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from pydantic import Field
44

5+
from .bom_item_field_calculation import BOMItemFieldCalculationData, BOMItemFieldCalculationEvent
56
from .custom_operations import (
67
CustomOperationDocumentData,
78
CustomOperationDocumentEvent,
@@ -37,6 +38,7 @@
3738
| PartReleasedEvent
3839
| PartReleaseCheckEvent
3940
| PartFieldCalculationEvent
41+
| BOMItemFieldCalculationEvent
4042
| FieldValueCalculationEvent
4143
| DummyEvent
4244
| EngineeringChangeReleasedEvent
@@ -59,6 +61,7 @@
5961
| PartReleasedData
6062
| PartReleaseCheckData
6163
| PartFieldCalculationData
64+
| BOMItemFieldCalculationData
6265
| FieldValueCalculationData
6366
| DummyEventData
6467
| EngineeringChangeReleasedData
@@ -81,6 +84,7 @@
8184
"PartReleasedEvent",
8285
"PartReleaseCheckEvent",
8386
"PartFieldCalculationEvent",
87+
"BOMItemFieldCalculationEvent",
8488
"FieldValueCalculationEvent",
8589
"DummyEvent",
8690
"EngineeringChangeReleasedEvent",
@@ -91,6 +95,7 @@
9195
"DocumentFieldCalculationData",
9296
"PartReleasedData",
9397
"PartReleaseCheckData",
98+
"BOMItemFieldCalculationData",
9499
"FieldValueCalculationData",
95100
"DummyEventData",
96101
"EngineeringChangeReleasedData",

csfunctions/events/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class EventNames(str, Enum):
1111
PART_RELEASED = "part_released"
1212
PART_RELEASE_CHECK = "part_release_check"
1313
PART_FIELD_CALCULATION = "part_field_calculation"
14+
BOM_ITEM_FIELD_CALCULATION = "bom_item_field_calculation"
1415
ENGINEERING_CHANGE_RELEASED = "engineering_change_released"
1516
ENGINEERING_CHANGE_RELEASE_CHECK = "engineering_change_release_check"
1617
FIELD_VALUE_CALCULATION = "field_value_calculation"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from typing import Literal
2+
3+
from pydantic import BaseModel, Field
4+
5+
from csfunctions.objects import BOMItem, Part
6+
from csfunctions.objects.document import Document
7+
8+
from .base import BaseEvent, EventNames
9+
10+
11+
class BOMItemFieldCalculationData(BaseModel):
12+
bom_item: BOMItem = Field(..., description="Current state of the BOM item")
13+
action: Literal["create", "modify", "copy", "index"] = Field(..., description="Action being performed")
14+
part: Part = Field(..., description="Part of the BOM item")
15+
documents: list[Document] = Field(..., description="List of documents that are referenced by the part.")
16+
17+
18+
class BOMItemFieldCalculationEvent(BaseEvent):
19+
name: Literal[EventNames.BOM_ITEM_FIELD_CALCULATION] = EventNames.BOM_ITEM_FIELD_CALCULATION
20+
data: BOMItemFieldCalculationData

csfunctions/objects/part.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ class Material(BaseObject):
234234
class BOMItem(BaseObject):
235235
object_type: Literal[ObjectType.BOM_ITEM] = ObjectType.BOM_ITEM
236236

237+
cdb_object_id: str | None = Field(None, description="Object ID")
238+
237239
baugruppe: str | None = Field(None, description="Assembly")
238240
b_index: str | None = Field(None, description="Assembly Index")
239241
component_materialnr_erp: str | None = Field(None, description="Material Number ERP Component")
@@ -247,3 +249,139 @@ class BOMItem(BaseObject):
247249
mengeneinheit: str | None = Field(None, description="Unit of Measure")
248250
teilenummer: str = Field(..., description="part number")
249251
t_index: str = Field(..., description="part index")
252+
253+
# Custom Char Fields
254+
cca_char_bom_item_1: str | None = Field(None, description="Custom Char Field")
255+
cca_char_bom_item_2: str | None = Field(None, description="Custom Char Field")
256+
cca_char_bom_item_3: str | None = Field(None, description="Custom Char Field")
257+
cca_char_bom_item_4: str | None = Field(None, description="Custom Char Field")
258+
cca_char_bom_item_5: str | None = Field(None, description="Custom Char Field")
259+
cca_char_bom_item_6: str | None = Field(None, description="Custom Char Field")
260+
cca_char_bom_item_7: str | None = Field(None, description="Custom Char Field")
261+
cca_char_bom_item_8: str | None = Field(None, description="Custom Char Field")
262+
cca_char_bom_item_9: str | None = Field(None, description="Custom Char Field")
263+
cca_char_bom_item_10: str | None = Field(None, description="Custom Char Field")
264+
cca_char_bom_item_11: str | None = Field(None, description="Custom Char Field")
265+
cca_char_bom_item_12: str | None = Field(None, description="Custom Char Field")
266+
cca_char_bom_item_13: str | None = Field(None, description="Custom Char Field")
267+
cca_char_bom_item_14: str | None = Field(None, description="Custom Char Field")
268+
cca_char_bom_item_15: str | None = Field(None, description="Custom Char Field")
269+
cca_char_bom_item_16: str | None = Field(None, description="Custom Char Field")
270+
cca_char_bom_item_17: str | None = Field(None, description="Custom Char Field")
271+
cca_char_bom_item_18: str | None = Field(None, description="Custom Char Field")
272+
cca_char_bom_item_19: str | None = Field(None, description="Custom Char Field")
273+
cca_char_bom_item_20: str | None = Field(None, description="Custom Char Field")
274+
# Custom BigChar Fields
275+
cca_bigchar_bom_item_1: str | None = Field(None, description="Custom BigChar Field")
276+
cca_bigchar_bom_item_2: str | None = Field(None, description="Custom BigChar Field")
277+
cca_bigchar_bom_item_3: str | None = Field(None, description="Custom BigChar Field")
278+
cca_bigchar_bom_item_4: str | None = Field(None, description="Custom BigChar Field")
279+
cca_bigchar_bom_item_5: str | None = Field(None, description="Custom BigChar Field")
280+
cca_bigchar_bom_item_6: str | None = Field(None, description="Custom BigChar Field")
281+
cca_bigchar_bom_item_7: str | None = Field(None, description="Custom BigChar Field")
282+
cca_bigchar_bom_item_8: str | None = Field(None, description="Custom BigChar Field")
283+
cca_bigchar_bom_item_9: str | None = Field(None, description="Custom BigChar Field")
284+
cca_bigchar_bom_item_10: str | None = Field(None, description="Custom BigChar Field")
285+
cca_bigchar_bom_item_11: str | None = Field(None, description="Custom BigChar Field")
286+
cca_bigchar_bom_item_12: str | None = Field(None, description="Custom BigChar Field")
287+
cca_bigchar_bom_item_13: str | None = Field(None, description="Custom BigChar Field")
288+
cca_bigchar_bom_item_14: str | None = Field(None, description="Custom BigChar Field")
289+
cca_bigchar_bom_item_15: str | None = Field(None, description="Custom BigChar Field")
290+
cca_bigchar_bom_item_16: str | None = Field(None, description="Custom BigChar Field")
291+
cca_bigchar_bom_item_17: str | None = Field(None, description="Custom BigChar Field")
292+
cca_bigchar_bom_item_18: str | None = Field(None, description="Custom BigChar Field")
293+
cca_bigchar_bom_item_19: str | None = Field(None, description="Custom BigChar Field")
294+
cca_bigchar_bom_item_20: str | None = Field(None, description="Custom BigChar Field")
295+
# Custom Integer Fields
296+
cca_integer_bom_item_1: int | None = Field(None, description="Custom Integer Field")
297+
cca_integer_bom_item_2: int | None = Field(None, description="Custom Integer Field")
298+
cca_integer_bom_item_3: int | None = Field(None, description="Custom Integer Field")
299+
cca_integer_bom_item_4: int | None = Field(None, description="Custom Integer Field")
300+
cca_integer_bom_item_5: int | None = Field(None, description="Custom Integer Field")
301+
cca_integer_bom_item_6: int | None = Field(None, description="Custom Integer Field")
302+
cca_integer_bom_item_7: int | None = Field(None, description="Custom Integer Field")
303+
cca_integer_bom_item_8: int | None = Field(None, description="Custom Integer Field")
304+
cca_integer_bom_item_9: int | None = Field(None, description="Custom Integer Field")
305+
cca_integer_bom_item_10: int | None = Field(None, description="Custom Integer Field")
306+
cca_integer_bom_item_11: int | None = Field(None, description="Custom Integer Field")
307+
cca_integer_bom_item_12: int | None = Field(None, description="Custom Integer Field")
308+
cca_integer_bom_item_13: int | None = Field(None, description="Custom Integer Field")
309+
cca_integer_bom_item_14: int | None = Field(None, description="Custom Integer Field")
310+
cca_integer_bom_item_15: int | None = Field(None, description="Custom Integer Field")
311+
cca_integer_bom_item_16: int | None = Field(None, description="Custom Integer Field")
312+
cca_integer_bom_item_17: int | None = Field(None, description="Custom Integer Field")
313+
cca_integer_bom_item_18: int | None = Field(None, description="Custom Integer Field")
314+
cca_integer_bom_item_19: int | None = Field(None, description="Custom Integer Field")
315+
cca_integer_bom_item_20: int | None = Field(None, description="Custom Integer Field")
316+
# Custom Float Fields
317+
cca_float_bom_item_1: float | None = Field(None, description="Custom Float Field")
318+
cca_float_bom_item_2: float | None = Field(None, description="Custom Float Field")
319+
cca_float_bom_item_3: float | None = Field(None, description="Custom Float Field")
320+
cca_float_bom_item_4: float | None = Field(None, description="Custom Float Field")
321+
cca_float_bom_item_5: float | None = Field(None, description="Custom Float Field")
322+
cca_float_bom_item_6: float | None = Field(None, description="Custom Float Field")
323+
cca_float_bom_item_7: float | None = Field(None, description="Custom Float Field")
324+
cca_float_bom_item_8: float | None = Field(None, description="Custom Float Field")
325+
cca_float_bom_item_9: float | None = Field(None, description="Custom Float Field")
326+
cca_float_bom_item_10: float | None = Field(None, description="Custom Float Field")
327+
cca_float_bom_item_11: float | None = Field(None, description="Custom Float Field")
328+
cca_float_bom_item_12: float | None = Field(None, description="Custom Float Field")
329+
cca_float_bom_item_13: float | None = Field(None, description="Custom Float Field")
330+
cca_float_bom_item_14: float | None = Field(None, description="Custom Float Field")
331+
cca_float_bom_item_15: float | None = Field(None, description="Custom Float Field")
332+
cca_float_bom_item_16: float | None = Field(None, description="Custom Float Field")
333+
cca_float_bom_item_17: float | None = Field(None, description="Custom Float Field")
334+
cca_float_bom_item_18: float | None = Field(None, description="Custom Float Field")
335+
cca_float_bom_item_19: float | None = Field(None, description="Custom Float Field")
336+
cca_float_bom_item_20: float | None = Field(None, description="Custom Float Field")
337+
# Custom Boolean Fields
338+
cca_bool_bom_item_1: bool | None = Field(None, description="Custom Boolean Field")
339+
cca_bool_bom_item_2: bool | None = Field(None, description="Custom Boolean Field")
340+
cca_bool_bom_item_3: bool | None = Field(None, description="Custom Boolean Field")
341+
cca_bool_bom_item_4: bool | None = Field(None, description="Custom Boolean Field")
342+
cca_bool_bom_item_5: bool | None = Field(None, description="Custom Boolean Field")
343+
cca_bool_bom_item_6: bool | None = Field(None, description="Custom Boolean Field")
344+
cca_bool_bom_item_7: bool | None = Field(None, description="Custom Boolean Field")
345+
cca_bool_bom_item_8: bool | None = Field(None, description="Custom Boolean Field")
346+
cca_bool_bom_item_9: bool | None = Field(None, description="Custom Boolean Field")
347+
cca_bool_bom_item_10: bool | None = Field(None, description="Custom Boolean Field")
348+
cca_bool_bom_item_11: bool | None = Field(None, description="Custom Boolean Field")
349+
cca_bool_bom_item_12: bool | None = Field(None, description="Custom Boolean Field")
350+
cca_bool_bom_item_13: bool | None = Field(None, description="Custom Boolean Field")
351+
cca_bool_bom_item_14: bool | None = Field(None, description="Custom Boolean Field")
352+
cca_bool_bom_item_15: bool | None = Field(None, description="Custom Boolean Field")
353+
cca_bool_bom_item_16: bool | None = Field(None, description="Custom Boolean Field")
354+
cca_bool_bom_item_17: bool | None = Field(None, description="Custom Boolean Field")
355+
cca_bool_bom_item_18: bool | None = Field(None, description="Custom Boolean Field")
356+
cca_bool_bom_item_19: bool | None = Field(None, description="Custom Boolean Field")
357+
cca_bool_bom_item_20: bool | None = Field(None, description="Custom Boolean Field")
358+
# Custom Date Fields
359+
cca_date_bom_item_1: datetime | None = Field(None, description="Custom Date Field")
360+
cca_date_bom_item_2: datetime | None = Field(None, description="Custom Date Field")
361+
cca_date_bom_item_3: datetime | None = Field(None, description="Custom Date Field")
362+
cca_date_bom_item_4: datetime | None = Field(None, description="Custom Date Field")
363+
cca_date_bom_item_5: datetime | None = Field(None, description="Custom Date Field")
364+
cca_date_bom_item_6: datetime | None = Field(None, description="Custom Date Field")
365+
cca_date_bom_item_7: datetime | None = Field(None, description="Custom Date Field")
366+
cca_date_bom_item_8: datetime | None = Field(None, description="Custom Date Field")
367+
cca_date_bom_item_9: datetime | None = Field(None, description="Custom Date Field")
368+
cca_date_bom_item_10: datetime | None = Field(None, description="Custom Date Field")
369+
cca_date_bom_item_11: datetime | None = Field(None, description="Custom Date Field")
370+
cca_date_bom_item_12: datetime | None = Field(None, description="Custom Date Field")
371+
cca_date_bom_item_13: datetime | None = Field(None, description="Custom Date Field")
372+
cca_date_bom_item_14: datetime | None = Field(None, description="Custom Date Field")
373+
cca_date_bom_item_15: datetime | None = Field(None, description="Custom Date Field")
374+
cca_date_bom_item_16: datetime | None = Field(None, description="Custom Date Field")
375+
cca_date_bom_item_17: datetime | None = Field(None, description="Custom Date Field")
376+
cca_date_bom_item_18: datetime | None = Field(None, description="Custom Date Field")
377+
cca_date_bom_item_19: datetime | None = Field(None, description="Custom Date Field")
378+
cca_date_bom_item_20: datetime | None = Field(None, description="Custom Date Field")
379+
380+
part: Part | None = Field(None, description="Part of the BOM item", exclude=True)
381+
382+
def link_objects(self, data: "EventData"):
383+
parts = get_items_of_type(data, Part)
384+
for part in parts:
385+
if part.teilenummer == self.teilenummer and part.t_index == self.t_index:
386+
self.part = part
387+
break

csfunctions/util.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@ def get_items_of_type(model: BaseModel, target_type: type[T]) -> list[T]:
2626
for item in attr:
2727
if isinstance(item, target_type):
2828
items.append(item)
29+
elif isinstance(attr, target_type):
30+
items.append(attr)
2931
return items

docs/reference/events.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,25 @@ The event expects a DataResponse containing a dictionary of field names and thei
265265
| documents | list[[Document](objects.md#document)] | List of documents that belong to the part |
266266

267267

268+
## BOMItemFieldCalculationEvent
269+
`csfunctions.events.BOMItemFieldCalculationEvent`
270+
271+
This event is fired when a BOM item is created, modified, copied or indexed. It is triggered after the field calculations defined in the datasheet editor are performed.
272+
273+
The event expects a DataResponse containing a dictionary of field names and their new values. Fields that are not mentioned in the response are not updated.
274+
275+
**BOMItemFieldCalculationEvent.name:** bom_item_field_calculation
276+
277+
**BOMItemFieldCalculationEvent.data:**
278+
279+
| Attribute | Type | Description |
280+
| --------- | -------------------------------------------- | -------------------------------------------------- |
281+
| bom_item | [BOMItem](objects.md#bomitem) | Current state of the BOM item |
282+
| action | Literal["create", "modify", "copy", "index"] | Action being performed |
283+
| part | [Part](objects.md#part) | Part of the BOM item |
284+
| documents | list[[Document](objects.md#document)] | List of documents that are referenced by the part. |
285+
286+
268287
## WorkflowTaskTriggerEvent
269288
`csfunctions.events.WorkflowTaskTriggerEvent`
270289

0 commit comments

Comments
 (0)