Skip to content

Commit 83f56b4

Browse files
author
Jens Kürten
committed
fix grammar mistakes
1 parent 5098cce commit 83f56b4

File tree

6 files changed

+73
-82
lines changed

6 files changed

+73
-82
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Functions are deeply integrated in the CIM Database Cloud Webhooks technology. T
1212

1313
Python 3.10+
1414

15-
csfunctions is build with [Pydantic 2](https://docs.pydantic.dev/latest/)
15+
csfunctions is built with [Pydantic 2](https://docs.pydantic.dev/latest/)
1616

1717
## Installation
1818
Install using pip:

docs/development_server.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
# Development Server
2+
13
The Functions SDK includes a development server that allows you to run your Functions in your development environment. The server reads Functions from the `environment.yaml` file and makes them available via HTTP endpoints. You can then connect these Functions to your CIM Database Cloud instance using webhooks.
24

3-
This speeds up the development of Functions, because you can instantly test your changes, without deploying them to the cloud infrastructure first.
5+
This speeds up the development of Functions because you can instantly test your changes without deploying them to the cloud infrastructure first.
46

57
## Starting the Server
68

@@ -16,7 +18,7 @@ You can set the port of the server using the `--port` flag (default is 8000), or
1618
python -m csfunctions.devserver --port 8080
1719
```
1820

19-
You can set the directory containing the `environment.yaml` file using the `--dir` flag (by default the current working directory is used) or by setting the `CON_DEV_DIR` environment variable:
21+
You can set the directory containing the `environment.yaml` file using the `--dir` flag (by default, the current working directory is used) or by setting the `CON_DEV_DIR` environment variable:
2022

2123
```bash
2224
python -m csfunctions.devserver --dir ./my_functions
@@ -32,7 +34,7 @@ python -m csfunctions.devserver --secret my_secret
3234

3335
The development server will automatically restart if you make changes to your Functions code or to the `environment.yaml` file.
3436

35-
## Exposing the server
37+
## Exposing the Server
3638

3739
To enable your CIM Database Cloud instance to send webhook requests to your Functions, you need to make the server accessible from the internet. Here are several ways to do this:
3840

@@ -50,26 +52,25 @@ If you are developing Functions locally, you can use services like [ngrok](https
5052

5153
Please refer to the documentation of the specific service for instructions on how to do this.
5254

53-
54-
## Create a webhook in CIM Database Cloud
55+
## Create a Webhook in CIM Database Cloud
5556

5657
To test your Functions locally, create a webhook in your CIM Database Cloud instance and point it to your development server.
5758

5859
The webhook URL should combine your development server URL with the Function name from your `environment.yaml` file using this format:
5960

6061
`https://<development-server-url>/<function-name>`
6162

62-
For example the `example` function would be available at:
63-
64-
```https://mycodespace-5g7grjgvrv9h4jrx-8000.app.github.dev/example```
63+
For example, the `example` function would be available at:
6564

65+
```
66+
https://mycodespace-5g7grjgvrv9h4jrx-8000.app.github.dev/example
67+
```
6668

67-
Make sure to set the webhooks event to the correct event you want to test with your Function.
69+
Make sure to set the webhook's event to the correct event you want to test with your Function.
6870

6971
For more detailed information on how to create a webhook in CIM Database Cloud, please refer to the [CIM Database Cloud documentation](https://saas-docs.contact-cloud.com/2025.7.0-en/admin/admin-contact_cloud/saas_admin/webhooks).
7072

71-
72-
## Securing the development server
73+
## Securing the Development Server
7374

7475
Since the development server is exposed to the outside world, you should secure it to prevent unauthorized access.
7576

docs/examples/enforce_field_rules.md

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
Functions can be used to validate user input and thus ensure that fields on e.g. parts or documents are filled out correctly.
1+
Functions can be used to validate user input and ensure that fields on, for example, parts or documents are filled out correctly.
22

33

44
### Required field based on Part category
5-
This example shows how you can enforce parts of category *"Single Part"* to have a material assigned to them.
5+
This example shows how you can enforce that parts in the category *"Single Part"* must have a material assigned.
66

7-
The example Function can be connected to the [PartCreateCheckEvent](../reference/events.md#partcreatecheckevent) and [PartModifyCheckEvent](../reference/events.md#partmodifycheckevent) and will return an [AbortAndShowErrorAction](../reference/actions.md#abortandshowerroraction) to abort the creation or modification of the part if the condition is not met.
7+
The example Function can be connected to the [PartCreateCheckEvent](../reference/events.md#partcreatecheckevent) and [PartModifyCheckEvent](../reference/events.md#partmodifycheckevent). It will return an [AbortAndShowErrorAction](../reference/actions.md#abortandshowerroraction) to abort the creation or modification of the part if the condition is not met.
88

99
```python
1010
from csfunctions import MetaData, Service
@@ -21,33 +21,32 @@ def single_part_needs_material(
2121
service: Service,
2222
):
2323
"""
24-
If a part of category ' Single Part' is created, a material has to be assigned.
24+
If a part of category 'Single Part' is created or modified, a material must be assigned.
2525
This should be checked when the part is created or modified.
2626
"""
2727

2828
for part in event.data.parts:
29-
# the event contains a list of parts that are about to be created
29+
# The event contains a list of parts that are about to be created or modified
3030
if part.t_kategorie_name_en == "Single Part" and not part.material_object_id:
3131
return AbortAndShowErrorAction(
32-
message="A material has to be assigned to a part of category 'Single Part'."
32+
message="A material must be assigned to a part of category 'Single Part'."
3333
)
3434

3535
```
3636

3737
### Require parts to be classified before release
3838

39-
Classification is a powerful tool for organizing your parts, however the best tool only works if users use it.
40-
With this example Function you can require parts to be classified before they can be released.
39+
Classification is a powerful tool for organizing your parts. However, even the best tool is only effective if users actually use it.
40+
With this example Function, you can require that parts are classified before they can be released.
4141

42-
This Function should be connected to the [PartReleaseCheckEvent](../reference/events.md#partreleasecheckevent) and will return an [AbortAndShowErrorAction](../reference/actions.md#abortandshowerroraction) to prevent the release, if classification data is missing.
42+
This Function should be connected to the [PartReleaseCheckEvent](../reference/events.md#partreleasecheckevent) and will return an [AbortAndShowErrorAction](../reference/actions.md#abortandshowerroraction) to prevent the release if classification data is missing.
4343

44-
The example code shows you how to fetch classification data for parts from the [CIM Database Cloud GraphQL API](https://saas-docs.contact-cloud.com/latest-en/admin/admin-contact_cloud/saas_admin/webhooks_graphql){:target="_blank"}. The Function then checks if any classification data is present, however you can easily expand this to check for specific classes.
44+
The example code demonstrates how to fetch classification data for parts from the [CIM Database Cloud GraphQL API](https://saas-docs.contact-cloud.com/latest-en/admin/admin-contact_cloud/saas_admin/webhooks_graphql){:target="_blank"}. The Function then checks if any classification data is present, but you can easily expand this to check for specific classes.
4545

4646
```python
4747
from csfunctions import MetaData, Service
4848
from csfunctions.actions import AbortAndShowErrorAction
4949
from csfunctions.events import (
50-
5150
PartReleaseCheckEvent,
5251
)
5352
import requests
@@ -80,16 +79,16 @@ def fetch_part_classification_property_codes(cdb_object_id: str, metadata: MetaD
8079

8180
def parts_need_classification(
8281
metadata: MetaData,
83-
event: PartReleaseCheckEvent ,
82+
event: PartReleaseCheckEvent,
8483
service: Service,
8584
):
8685
"""
87-
Parts need to be classified before they can be released.
86+
Parts must be classified before they can be released.
8887
"""
8988

9089
for part in event.data.parts:
91-
# the event contains a list of parts that are about to be released
92-
# for each part fetch the classification property codes and check if they are empty
90+
# The event contains a list of parts that are about to be released
91+
# For each part, fetch the classification property codes and check if they are empty
9392
property_codes = fetch_part_classification_property_codes(part.cdb_object_id, metadata)
9493
if not property_codes:
9594
return AbortAndShowErrorAction(

docs/examples/field_calculation.md

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
# Field calculation
22

3-
The data sheet editor in CIM Database Cloud already allows you to define some basic [field calculations](https://saas-docs.contact-cloud.com/2025.13.1-en/admin/admin-contact_cloud/saas_admin/app_setup_data_edit_field_calc){:target="_blank"} to fill out fields automatically.
3+
The datasheet editor in CIM Database Cloud already allows you to define some basic [field calculations](https://saas-docs.contact-cloud.com/2025.13.1-en/admin/admin-contact_cloud/saas_admin/app_setup_data_edit_field_calc){:target="_blank"} to fill out fields automatically.
44

5-
However, the Python expressions available in the datasheet editor are limited. Functions allow for much more freedom in defining your field calculations, and allow you to do things like *"fetching external data"* or *"referencing other objects"*.
5+
However, the Python expressions available in the datasheet editor are limited. Functions allow for much more flexibility in defining your field calculations, enabling you to do things like *fetching external data* or *referencing other objects*.
66

7-
Field calculations with Functions utilize the "<Object\>FieldCalulationEvent", e.g. [PartFieldCalculationEvent](../reference/events.md#partfieldcalculationevent), which expect the response to contain a `DataResponse` with a dictionary containing the fields that should be updated.
7+
Field calculations with Functions utilize the `<Object>FieldCalculationEvent`, e.g. [PartFieldCalculationEvent](../reference/events.md#partfieldcalculationevent), which expects the response to contain a `DataResponse` with a dictionary of the fields that should be updated.
88

99
```python
10-
return DataResponse(data={somefield="new value"})
10+
return DataResponse(data={"somefield": "new value"})
1111
```
1212

1313

1414
## Custom part number for external parts
1515

16-
This example shows you the basics of calculating fields with Functions and how to use the `service` parameter to generate a fresh number.
16+
This example shows you the basics of calculating fields with Functions and how to use the `service` parameter to generate a new number.
1717

1818
The example Function checks if the part is an *"External"* part and generates a custom part number for it.
1919

@@ -23,59 +23,53 @@ from csfunctions.events import PartFieldCalculationEvent
2323
from csfunctions.metadata import MetaData
2424
from csfunctions.service import Service
2525

26-
2726
def calculate_part_number(metadata: MetaData, event: PartFieldCalculationEvent, service: Service):
2827
"""
2928
Example Function.
30-
This function is triggered when a part fields should be calculated.
31-
For "External" parts we want to set the part number as "E-000123".
29+
This function is triggered when a part field should be calculated.
30+
For "External" parts, we want to set the part number as "E-000123".
3231
All other parts should keep the standard part number.
33-
3432
"""
3533
if event.data.action != "create":
36-
# part number can only be set when the part is created
34+
# Part number can only be set when the part is created
3735
return
3836

39-
# match "External Single Part" or "External Assembly"
37+
# Match "External Single Part" or "External Assembly"
4038
if event.data.part.t_kategorie_name_en.startswith("External"):
41-
42-
# generate a new number using the service
39+
# Generate a new number using the service
4340
new_number = service.generator.get_number("external_part_number")
44-
4541
# new_number is an integer, so we need to convert it to a string
4642
# and pad it with leading zeros to 6 digits
4743
new_part_number = str(new_number).zfill(6)
48-
49-
# then add the prefix "E-" to the number
44+
# Add the prefix "E-" to the number
5045
new_part_number = "E-" + new_part_number
51-
52-
# finally we return the new part number (teilenummer)
46+
# Return the new part number (teilenummer)
5347
return DataResponse(data={"teilenummer": new_part_number})
5448
```
5549

5650
!!! tip
57-
You can check `event.data.action` to decide for which operations (*copy*,*create*,*index* and *modify*) you want your field calculation to return a new value.
58-
Some fields, like part number (*teilenummer*) can only be set during the initial creation.
51+
You can check `event.data.action` to decide for which operations (*copy*, *create*, *index*, and *modify*) you want your field calculation to return a new value.
52+
Some fields, like part number (*teilenummer*), can only be set during the initial creation.
5953

6054
## Translate a field with DeepL
6155

62-
Inside Functions you can fetch data from external systems and fill out fields based on that data. This is something that would not be possible with the field calculations in the datasheet editor. You could use this for example to fetch new part numbers from an ERP system.
56+
Inside Functions, you can fetch data from external systems and fill out fields based on that data. This is something that would not be possible with the field calculations in the datasheet editor. For example, you could use this to fetch new part numbers from an ERP system.
6357

64-
This example uses the API from [DeepL](https://www.deepl.com) to translate a field from German to English. The example uses the additional attributes 1 and 2 on parts, but you can of course change that to any attributes that fit your use-case.
58+
This example uses the API from [DeepL](https://www.deepl.com) to translate a field from German to English. The example uses the additional attributes 1 and 2 on parts, but you can of course change that to any attributes that fit your use case.
6559

6660
```python
6761
import os
6862
from csfunctions import DataResponse
6963
from csfunctions.events import PartFieldCalculationEvent
7064
import requests
7165

72-
# set the DEEPL_API_KEY during deployment like this:
66+
# Set the DEEPL_API_KEY during deployment like this:
7367
# cfc env deploy <environment name> --environment-variables "DEEPL_API_KEY=<your API key>"
7468
DEEPL_API_KEY = os.getenv("DEEPL_API_KEY")
7569

7670
def part_field_calculation(metadata, event: PartFieldCalculationEvent, service):
7771
if event.data.action != "create":
78-
# only translate on creation
72+
# Only translate on creation
7973
return
8074

8175
if event.data.part.cssaas_frame_add_attr_1:

docs/examples/workflows.md

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
# Working with workflows
22

3-
Functions can interact with workflows. You can trigger Functions from within workflows using the [Trigger Webhook](https://saas-docs.contact-cloud.com/latest-en/admin/admin-contact_cloud/saas_admin/webhooks_workflow){:target="_blank"} task and you can even start new workflows by using the [StartWorkflowAction](../reference/actions.md#startworkflowaction)!
3+
Functions can interact with workflows. You can trigger Functions from within workflows using the [Trigger Webhook](https://saas-docs.contact-cloud.com/latest-en/admin/admin-contact_cloud/saas_admin/webhooks_workflow){:target="_blank"} task, and you can even start new workflows by using the [StartWorkflowAction](../reference/actions.md#startworkflowaction)!
44

55

6-
## Start workflow on EC status change
6+
## Start a workflow on EC status change
77

8-
This example shows you how to start a workflow template in response to an engineering change status change.
8+
This example shows how to start a workflow template in response to an engineering change status change.
99

1010
!!! note
11-
Starting workflows in response to engineering change status changes is already possible in CIM Database Cloud without the use of Functions. However Functions allow you to dynamically select different templates and fill out task parameters, based on the nature of the change.
11+
Starting workflows in response to engineering change status changes is already possible in CIM Database Cloud without the use of Functions. However, Functions allow you to dynamically select different templates and fill out task parameters based on the nature of the change.
1212

13-
This example uses a very simple template, containing just an *information task*. If an engineering change contains external parts, users with the *External Part Manager* Role should be notified of the planned change during the evaluation phase.
14-
15-
You can easily adapt this example to your use-case, by adding additional tasks to the template or changing the conditions under which the workflow should be started.
13+
This example uses a very simple template containing just an *information task*. If an engineering change contains external parts, users with the *External Part Manager* role should be notified of the planned change during the evaluation phase.
1614

15+
You can easily adapt this example to your use case by adding additional tasks to the template or changing the conditions under which the workflow should be started.
1716

1817
```python
1918
from csfunctions.actions.start_workflow import (
@@ -24,7 +23,7 @@ from csfunctions.actions.start_workflow import (
2423
from csfunctions.events import EngineeringChangeStatusChangedEvent
2524
from csfunctions import MetaData
2625

27-
# change these to match your template and roles!!!
26+
# Change these to match your template and roles!
2827
TEMPLATE_ID = "PT00000002"
2928
INFORMATION_TASK_ID = "T00000008"
3029
INFORM_ROLE = "External Part Manager"
@@ -34,42 +33,40 @@ def start_workflow_on_ec_status_change(
3433
metadata: MetaData, event: EngineeringChangeStatusChangedEvent, service
3534
):
3635
if event.data.engineering_change.status != 30:
37-
# only start the workflow if the status changed to 30 (Evaluation)
36+
# Only start the workflow if the status changed to 30 (Evaluation)
3837
return
3938

40-
# check if the ec contains external parts
39+
# Check if the EC contains external parts
4140
if not any(
4241
part.t_kategorie_name_en.startswith("External")
4342
for part in event.data.engineering_change.planned_changes_parts
4443
):
45-
# no external parts, so we don't need to start the workflow
44+
# No external parts, so we don't need to start the workflow
4645
return
4746

4847
return StartWorkflowAction(
4948
template_id=TEMPLATE_ID,
5049
title=f"Information about EC {event.data.engineering_change.cdb_ec_id}",
51-
# attach the engineering change to the workflow
50+
# Attach the engineering change to the workflow
5251
global_briefcase_object_ids=[
5352
event.data.engineering_change.cdb_object_id],
5453
task_configurations=[
5554
TaskConfiguration(
5655
task_id=INFORMATION_TASK_ID,
57-
description="A an engineering change containing external parts moved to the evaluation phase.",
56+
description="An engineering change containing external parts moved to the evaluation phase.",
5857
recipients=[
5958
Subject(
6059
subject_type="Common Role",
6160
subject_id=INFORM_ROLE,
6261
)
6362
],
6463
)
65-
6664
],
6765
)
6866
```
6967

7068
!!! note
71-
To sucessfully execute this example you need to:
72-
73-
- Create a workflow template with an information task and adjust the `TEMPLATE_ID` and `INFORMATION_TASK_ID` to match them
69+
To successfully execute this example, you need to:
7470

75-
- Create and assign an "External Part Manager" role to a user
71+
- Create a workflow template with an information task and adjust the `TEMPLATE_ID` and `INFORMATION_TASK_ID` to match them.
72+
- Create and assign an "External Part Manager" role to a user.

0 commit comments

Comments
 (0)