|
| 1 | +# Field calculation |
| 2 | + |
| 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. |
| 4 | + |
| 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"*. |
| 6 | + |
| 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. |
| 8 | + |
| 9 | +```python |
| 10 | +return DataResponse(data={somefield="new value"}) |
| 11 | +``` |
| 12 | + |
| 13 | + |
| 14 | +## Custom part number for external parts |
| 15 | + |
| 16 | +This example shows you the basics of calculating fields with Functions and how to use the `service` parameter to generate a fresh number. |
| 17 | + |
| 18 | +The example Function checks if the part is an *"External"* part and generates a custom part number for it. |
| 19 | + |
| 20 | +```python |
| 21 | +from csfunctions import DataResponse |
| 22 | +from csfunctions.events import PartFieldCalculationEvent |
| 23 | +from csfunctions.metadata import MetaData |
| 24 | +from csfunctions.service import Service |
| 25 | + |
| 26 | + |
| 27 | +def calculate_part_number(metadata: MetaData, event: PartFieldCalculationEvent, service: Service): |
| 28 | + """ |
| 29 | + 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". |
| 32 | + All other parts should keep the standard part number. |
| 33 | +
|
| 34 | + """ |
| 35 | + if event.data.action != "create": |
| 36 | + # part number can only be set when the part is created |
| 37 | + return |
| 38 | + |
| 39 | + # match "External Single Part" or "External Assembly" |
| 40 | + if event.data.part.t_kategorie_name_en.startswith("External"): |
| 41 | + |
| 42 | + # generate a new number using the service |
| 43 | + new_number = service.generator.get_number("external_part_number") |
| 44 | + |
| 45 | + # new_number is an integer, so we need to convert it to a string |
| 46 | + # and pad it with leading zeros to 6 digits |
| 47 | + new_part_number = str(new_number).zfill(6) |
| 48 | + |
| 49 | + # then add the prefix "E-" to the number |
| 50 | + new_part_number = "E-" + new_part_number |
| 51 | + |
| 52 | + # finally we return the new part number (teilenummer) |
| 53 | + return DataResponse(data={"teilenummer": new_part_number}) |
| 54 | +``` |
| 55 | + |
| 56 | +!!! 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. |
| 59 | + |
| 60 | +## Translate a field with DeepL |
| 61 | + |
| 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. |
| 63 | + |
| 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. |
| 65 | + |
| 66 | +```python |
| 67 | +import os |
| 68 | +from csfunctions import DataResponse |
| 69 | +from csfunctions.events import PartFieldCalculationEvent |
| 70 | +import requests |
| 71 | + |
| 72 | +# set the DEEPL_API_KEY during deployment like this: |
| 73 | +# cfc env deploy <environment name> --environment-variables "DEEPL_API_KEY=<your API key>" |
| 74 | +DEEPL_API_KEY = os.getenv("DEEPL_API_KEY") |
| 75 | + |
| 76 | +def part_field_calculation(metadata, event: PartFieldCalculationEvent, service): |
| 77 | + if event.data.action != "create": |
| 78 | + # only translate on creation |
| 79 | + return |
| 80 | + |
| 81 | + if event.data.part.cssaas_frame_add_attr_1: |
| 82 | + translated_text = translate_text( |
| 83 | + event.data.part.cssaas_frame_add_attr_1, "EN", "DE") |
| 84 | + return DataResponse(data={"cssaas_frame_add_attr_2": translated_text}) |
| 85 | + |
| 86 | +def translate_text(text, target_lang, source_lang=None): |
| 87 | + url = "https://api-free.deepl.com/v2/translate" |
| 88 | + data = { |
| 89 | + "auth_key": DEEPL_API_KEY, |
| 90 | + "text": text, |
| 91 | + "target_lang": target_lang.upper() |
| 92 | + } |
| 93 | + if source_lang: |
| 94 | + data["source_lang"] = source_lang.upper() |
| 95 | + |
| 96 | + response = requests.post(url, data=data) |
| 97 | + response.raise_for_status() |
| 98 | + return response.json()["translations"][0]["text"] |
| 99 | + |
| 100 | +``` |
| 101 | + |
| 102 | +!!! note |
| 103 | + This example requires a DeepL API key to function. Adding secrets like API keys to your code is a bad practice, which is why the example fetches the API key from an environment variable. |
| 104 | + |
| 105 | + You can set environment variables during deployment of your Function to the CIM Database Cloud Functions infrastructure like this: |
| 106 | + |
| 107 | + `cfc env deploy <environment name> --environment-variables "DEEPL_API_KEY=<your API key>"` |
0 commit comments