{"id":19755838,"url":"https://github.com/cap-js/change-tracking","last_synced_at":"2026-03-11T20:00:56.074Z","repository":{"id":200942620,"uuid":"608399564","full_name":"cap-js/change-tracking","owner":"cap-js","description":"CDS plugin providing out-of-the box support for automatic capturing, storing, and viewing of the change records of modeled entities.","archived":false,"fork":false,"pushed_at":"2026-03-11T16:26:29.000Z","size":4339,"stargazers_count":40,"open_issues_count":18,"forks_count":15,"subscribers_count":11,"default_branch":"main","last_synced_at":"2026-03-11T16:33:08.467Z","etag":null,"topics":["btp","cap","cds","change-tracking","nodejs","plugin","sap-btp","sap-cap"],"latest_commit_sha":null,"homepage":"https://cap.cloud.sap/docs","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cap-js.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-03-01T23:53:45.000Z","updated_at":"2026-03-09T09:34:26.000Z","dependencies_parsed_at":"2025-12-17T23:00:52.908Z","dependency_job_id":"fcba7d94-17d7-4cd5-bef9-758d066ca1a7","html_url":"https://github.com/cap-js/change-tracking","commit_stats":{"total_commits":82,"total_committers":14,"mean_commits":5.857142857142857,"dds":0.6951219512195121,"last_synced_commit":"0fd23c3d8ee5bb82f2f0f32b157c64e3d3195062"},"previous_names":["cap-js/change-tracking"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/cap-js/change-tracking","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cap-js%2Fchange-tracking","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cap-js%2Fchange-tracking/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cap-js%2Fchange-tracking/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cap-js%2Fchange-tracking/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cap-js","download_url":"https://codeload.github.com/cap-js/change-tracking/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cap-js%2Fchange-tracking/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30398148,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T18:46:22.935Z","status":"ssl_error","status_checked_at":"2026-03-11T18:46:17.045Z","response_time":84,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["btp","cap","cds","change-tracking","nodejs","plugin","sap-btp","sap-cap"],"created_at":"2024-11-12T03:13:38.728Z","updated_at":"2026-03-11T20:00:56.068Z","avatar_url":"https://github.com/cap-js.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Change Tracking Plugin for SAP Cloud Application Programming Model (CAP)\n\na [CDS plugin](https://cap.cloud.sap/docs/node.js/cds-plugins#cds-plugin-packages) for automatic capturing, storing, and viewing of the change records of modeled entities\n\n[![REUSE status](https://api.reuse.software/badge/github.com/cap-js/change-tracking)](https://api.reuse.software/info/github.com/cap-js/change-tracking)\n\n\u003e [!IMPORTANT]\n\u003e With version 2.0 we completely refactored how changes are tracked. Previously the logic was completely on the application layer, which limited the types of queries trackable and came with major performance penalties in larger projects. With v2.0 the changes are now fully tracked on the database layer via database triggers. Furthermore with v2.0 the table definition for changes was cleaned up. This means any upgrade involves a schema change.\n\n\n### Table of Contents\n\n- [Try it Locally](#try-it-locally)\n- [Detailed Explanation](#detailed-explanation)\n  - [Human-readable Types and Fields](#human-readable-types-and-fields)\n  - [Human-readable IDs](#human-readable-ids)\n  - [Human-readable Values](#human-readable-values)\n- [Advanced Options](#advanced-options)\n  - [Altered Table View](#altered-table-view)\n  - [Disable Lazy Loading](#disable-lazy-loading)\n  - [Disable UI Facet generation](#disable-ui-facet-generation)\n    - [Disable Association to Changes Generation](#disable-association-to-changes-generation)\n- [Examples](#examples)\n  - [Specify Object ID](#specify-object-id)\n  - [Tracing Changes](#tracing-changes)\n  - [Don\u0026#39;ts](#donts)\n- [Contributing](#contributing)\n- [Code of Conduct](#code-of-conduct)\n- [Licensing](#licensing)\n\n## Try it Locally\n\nTo enable change tracking, simply add this self-configuring plugin package to your project:\n\n```sh\nnpm add @cap-js/change-tracking\n```\n\n\u003e [!Warning]\n\u003e\n\u003e Please note that if your project is multi-tenant, then the CDS version must be higher than 8.6 and the mtx version higher than 2.5 for change-tracking to work.\n\n\u003e [!Warning]\n\u003e\n\u003e When using multi-tenancy with MTX, the generated database triggers, facets and associations have to be created by the model provider of the MTX component. Therefore, the plugin also must be added to the `package.json` of the MTX sidecar. \n\n### Annotations\n\n\u003e [!WARNING]\n\u003e Please be aware that [**sensitive** or **personal** data](https://cap.cloud.sap/docs/guides/data-privacy/annotations#annotating-personal-data) (annotated with `@PersonalData`) is not change tracked, since viewing the log allows users to circumvent [audit-logging](https://cap.cloud.sap/docs/guides/data-privacy/audit-logging#setup).\n\nAll you need to do is to identify what should be change-tracked by annotating respective entities and elements in our model with the `@changelog` annotation. Following the [best practice of separation of concerns](https://cap.cloud.sap/docs/guides/domain-modeling#separation-of-concerns), we do so in a separate file _db/change-tracking.cds_:\n\n```cds\nusing { sap.capire.Incidents, sap.capire.Conversations } from './schema.cds';\n\nannotate Incidents {\n  customer @changelog: [customer.name];\n  title    @changelog;\n  status   @changelog;\n}\n\nannotate Conversations with @changelog: [author, timestamp] {\n  message  @changelog @Common.Label: 'Message';\n}\n```\n\nThe minimal annotation we require for change tracking is `@changelog` on elements, as for the elements `title` and `status` in the sample snippet above.\n\nAdditional identifiers or labels can be added to obtain more *human-readable* change records as described below.\n\n### Testing\n\nWith the steps above, we have successfully set up change tracking for our reference application. Let's see that in action.\n\n1. **Start the server**:\n\n```sh\ncds watch\n```\n\n2. **Make a change** on your change-tracked elements. This change will automatically be persisted in the database table (`sap.changelog.Changes`) and made available in a pre-defined view, namely the [Change History view](#change-history-view) for your convenience.\n\n#### Change History View\n\n\u003e [!IMPORTANT]\n\u003e To ensure proper lazy loading of the Change History table, please use **SAPUI5 version 1.120.0** or higher.`\u003cbr\u003e`\n\u003e If you wish to *disable* this feature, please see the customization section on how to [disable lazy loading](#disable-lazy-loading).\n\n\u003cimg width=\"1300\" alt=\"change-history\" src=\"_assets/changes.png\"\u003e\n\nIf you have a Fiori Element application, the CDS plugin automatically provides and generates a view `sap.changelog.ChangeView`, the facet of which is automatically added to the Fiori Object Page of your change-tracked entities/elements. In the UI, this corresponds to the *Change History* table which serves to help you to view and search the stored change records of your modeled entities.\n\n## Detailed Explanation\n\n### Human-readable Types and Fields\n\nBy default the implementation looks up *Object Type* names or *Field* names from respective  `@title` or  `@Common.Label` annotations, and applies i18n lookups. If no such annotations are given, the technical names of the respective CDS definitions are displayed.\n\nFor example, without the `@title` annotation, changes to conversation entries would show up with the technical entity name:\n\n\u003cimg width=\"1300\" alt=\"change-history-type\" src=\"_assets/changes-type-wbox.png\"\u003e\n\nWith an annotation, and possible i18n translations like so:\n\n```cds\nannotate Conversations with @title: 'Conversations';\n```\n\nWe get a human-readable display for *Object Type*:\n\n\u003cimg width=\"1300\" alt=\"change-history-type-hr\" src=\"_assets/changes-type-hr-wbox.png\"\u003e\n\n### Human-readable IDs\n\nThe changelog annotations for *Object ID* are defined at entity level.\n\nThese are already human-readable by default, unless the `@changelog` definition cannot be uniquely mapped such as types `enum` or `Association`.\n\nFor example, having a `@changelog` annotation without any additional identifiers, changes to conversation entries would show up as simple entity IDs:\n\n\u003cimg width=\"1300\" alt=\"change-history-id\" src=\"_assets/changes-id-wbox.png\"\u003e\n\nHowever, this is not advisable as we cannot easily distinguish between changes. It is more appropriate to annotate as follows:\n\n```cds\nannotate ProcessorService.Conversations with @changelog: [author, timestamp] {\n```\n\n\u003cimg width=\"1300\" alt=\"change-history-id-hr\" src=\"_assets/changes-id-hr-wbox.png\"\u003e\n\nExpanding the changelog annotation by additional identifiers `[author, timestamp]`, we can now better identify the `message` change events by their respective author and timestamp.\n\n### Human-readable Values\n\nThe changelog annotations for *New Value* and *Old Value* are defined at element level.\n\nThey are already human-readable by default, unless the `@changelog` definition cannot be uniquely mapped such as types `enum` or `Association`.\n\nFor example, having a `@changelog` annotation without any additional identifiers, changes to incident customer would show up as UUIDs:\n\n```cds\ncustomer @changelog;\n```\n\n\u003cimg width=\"1300\" alt=\"change-history-value\" src=\"_assets/changes-value-wbox.png\"\u003e\n\nHence, here it is essential to add a unique identifier to obtain human-readable value columns:\n\n```cds\ncustomer @changelog: [customer.name];\n```\n\n\u003cimg width=\"1300\" alt=\"change-history-value-hr\" src=\"_assets/changes-value-hr-wbox.png\"\u003e\n\n## Advanced Options\n\n### Altered table view\n\nThe *Change History* view can be easily adapted and configured to your own needs by simply changing or extending it. For example, let's assume we only want to show the first 5 columns in equal spacing, we would extend `srv/change-tracking.cds` as follows:\n\n```cds\nusing from '@cap-js/change-tracking';\n\nannotate sap.changelog.ChangeView with @(\n  UI.LineItem : [\n    { Value: modification, @HTML5.CssDefaults: { width:'20%' }},\n    { Value: createdAt,    @HTML5.CssDefaults: { width:'20%' }},\n    { Value: createdBy,    @HTML5.CssDefaults: { width:'20%' }},\n    { Value: entity,       @HTML5.CssDefaults: { width:'20%' }},\n    { Value: objectID,     @HTML5.CssDefaults: { width:'20%' }}\n  ]\n);\n```\n\nIn the UI, the *Change History* table now contains 5 equally-spaced columns with the desired properties:\n\n\u003cimg width=\"1300\" alt=\"change-history-custom\" src=\"_assets/changes-custom.png\"\u003e\n\nFor more information and examples on adding Fiori Annotations, see [Adding SAP Fiori Annotations](https://cap.cloud.sap/docs/advanced/fiori#fiori-annotations).\n\n### Disable lazy loading\n\nTo disable the lazy loading feature of the *Change History* table, you can add the following annotation to your `srv/change-tracking.cds`:\n\n```cds\nusing from '@cap-js/change-tracking';\n\nannotate sap.changelog.aspect @(UI.Facets: [{\n  $Type : 'UI.ReferenceFacet',\n  ID    : 'ChangeHistoryFacet',\n  Label : '{i18n\u003eChangeHistory}',\n  Target: 'changes/@UI.PresentationVariant',\n  ![@UI.PartOfPreview]\n}]);\n```\n\nThe system now uses the SAPUI5 default setting `![@UI.PartOfPreview]: true`, such that the table will always shown when navigating to that respective Object page.\n\n### Disable UI Facet generation\n\nIf you do not want the auto-provided UI facet for viewing changes, you can provide your own facet for the `changes` association in the `@UI.Facets` annotation and the plugin won't override it.\n\nFurthermore if you annotate the association as not readable, the facet is also not added. You can achive this, like \n\n```cds\n@Capabilities.NavigationRestrictions.RestrictedProperties : [\n  {\n    NavigationProperty : changes,\n    ReadRestrictions : {\n      Readable : false,\n    },\n  },\n]\nentity SalesOrders {\n  key ID : Int16;\n      title  : String @changelog;\n}\n```\n\n### Disable Association to Changes Generation\n\nFor some scenarios, e.g. when doing `UNION` and the `@changelog` annotion is still propageted, the automatic addition of the association to `changes` does not make sense. You can use `@changelog.disable_assoc`for this to be disabled on entity level.\n\n\u003e [!IMPORTANT]\n\u003e This will also supress the addition of the UI facet, since the change-view is not available as target entity anymore.\n\n### Select types of changes to track\n\nIf you do not want to track some types of changes, you can disable them using `disableCreateTracking`, `disableUpdateTracking`\nand `disableDeleteTracking` configs in your project settings:\n```json\n{\n  \"cds\": {\n    \"requires\": {\n      \"change-tracking\": {\n        \"disableCreateTracking\": true,\n        \"disableUpdateTracking\": false,\n        \"disableDeleteTracking\": true\n      }\n    }\n  }\n}\n```\n\n### Preserve change logs of deleted data\n\nBy default, deleting a record will also automatically delete all associated change logs. This helps reduce the impact on the size of the database.\nYou can turn this behavior off globally by adding the following switch to the `package.json` of your project\n\n```json\n...\n\"cds\": {\n  \"requires\": {\n    ...\n    \"change-tracking\": {\n      \"preserveDeletes\": true\n    }\n   ...\n  }\n}\n...\n```\n\u003e [!IMPORTANT]\n\u003e Preserving the change logs of deleted data can have a significant impact on the size of the change logging table, since now such data also survives automated data retention runs. \n\u003e You must implement an own **data retention strategy** for the change logging table in order to manage the size and performance of your database.\n\n### Tracking localized values\n\nIf you are using a model like \n\n```cds\nentity Incidents : cuid, managed {\n  // … more fields\n  status         : Association to Status default 'N' @changelog : [status.descr];\n}\n\nentity Status {\n  key code    : String:\n  descr : localized String;\n}\n```\n\nyou can save the localized values into the change log instead of the default values, by setting `considerLocalizedValues`:\n\n```json\n...\n\"cds\": {\n  \"requires\": {\n    \"change-tracking\": {\n      \"considerLocalizedValues\": true\n    }\n  }\n}\n...\n```\n\nPlease be aware this means the localized value is then stored and shown in the change log, e.g. if a user speaking another language accesses the change log later, they will still see the value in the language used by the user who caused the change log.\n\n## Examples\n\nThis section describes modelling cases for further reference, from simple to complex, including the following:\n\n- [Specify Object ID](#specify-object-id)\n  - [Use Case 1: Annotate single field/multiple fields of associated table(s) as the Object ID](#use-case-1-annotate-single-fieldmultiple-fields-of-associated-tables-as-the-object-id)\n  - [Use Case 2: Annotate single field/multiple fields of project customized types as the Object ID](#use-case-2-annotate-single-fieldmultiple-fields-of-project-customized-types-as-the-object-id)\n  - [Use Case 3: Annotate chained associated entities from the current entity as the Object ID](#use-case-3-annotate-chained-associated-entities-from-the-current-entity-as-the-object-id)\n- [Tracing Changes](#tracing-changes)\n  - [Use Case 1: Trace the changes of child nodes from the current entity and display the meaningful data from child nodes (composition relation)](#use-case-1-trace-the-changes-of-child-nodes-from-the-current-entity-and-display-the-meaningful-data-from-child-nodes-composition-relation)\n  - [Use Case 2: Trace the changes of associated entities from the current entity and display the meaningful data from associated entities (association relation)](#use-case-2-trace-the-changes-of-associated-entities-from-the-current-entity-and-display-the-meaningful-data-from-associated-entities-association-relation)\n  - [Use Case 3: Trace the changes of fields defined by project customized types and display the meaningful data](#use-case-3-trace-the-changes-of-fields-defined-by-project-customized-types-and-display-the-meaningful-data)\n  - [Use Case 4: Trace the changes of chained associated entities from the current entity and display the meaningful data from associated entities (association relation)](#use-case-4-trace-the-changes-of-chained-associated-entities-from-the-current-entity-and-display-the-meaningful-data-from-associated-entities-association-relation)\n  - [Use Case 5: Trace the changes of union entity and display the meaningful data](#use-case-5-trace-the-changes-of-union-entity-and-display-the-meaningful-data)\n- [Don\u0026#39;ts](#donts)\n  - [Use Case 1: Don\u0026#39;t trace changes for field(s) with `Association to many`](#use-case-1-dont-trace-changes-for-fields-with-association-to-many)\n  - [Use Case 2: Don\u0026#39;t trace changes for field(s) with *Unmanaged Association*](#use-case-2-dont-trace-changes-for-fields-with-unmanaged-association)\n\n### Specify Object ID\n\nUse cases for Object ID annotation\n\n#### Use Case 1: Annotate single field/multiple fields of associated table(s) as the Object ID\n\nModelling in `db/schema.cds`\n\n```cds\nentity Incidents : cuid, managed {\n  ...\n  customer       : Association to Customers;\n  title          : String @title: 'Title';\n  urgency        : Association to Urgency default 'M';\n  status         : Association to Status default 'N';\n  ...\n}\n```\n\nAdd the following `@changelog` annotations in `srv/change-tracking.cds`\n\n```cds\nannotate ProcessorService.Incidents with @changelog: [customer.name, urgency.code, status.criticality] {\n  title    @changelog;\n}\n```\n\n![AssociationID](_assets/AssociationID.png)\n\n#### Use Case 2: Annotate single field/multiple fields of project customized types as the Object ID\n\nModelling in `db/schema.cds`\n\n```cds\nentity Incidents : cuid, managed {\n  ...\n  customer       : Association to Customers;\n  title          : String @title: 'Title';\n  ...\n}\n\nentity Customers : cuid, managed {\n  ...\n  email          : EMailAddress;  // customized type\n  phone          : PhoneNumber;   // customized type\n  ...\n}\n```\n\nAdd the following `@changelog` annotations in `srv/change-tracking.cds`\n\n```cds\nannotate ProcessorService.Incidents with @changelog: [customer.email, customer.phone] {\n  title    @changelog;\n}\n```\n\n![CustomTypeID](_assets/CustomTypeID.png)\n\n#### Use Case 3: Annotate chained associated entities from the current entity as the Object ID\n\nModelling in `db/schema.cds`\n\n```cds\nentity Incidents : cuid, managed {\n  ...\n  customer       : Association to Customers;\n  ...\n}\n\nentity Customers : cuid, managed {\n  ...\n  addresses : Association to Addresses;\n  ...\n}\n```\n\nAdd the following `@changelog` annotations in `srv/change-tracking.cds`\n\n```cds\nannotate ProcessorService.Incidents with @changelog: [customer.addresses.city, customer.addresses.postCode] {\n  title    @changelog;\n}\n```\n\n![ChainedAssociationID](_assets/ChainedAssociationID.png)\n\n\u003e Change-tracking supports annotating chained associated entities from the current entity as object ID of current entity in case the entity in consumer applications is a pure relation table. However, the usage of chained associated entities is not recommended due to performance cost.\n\n### Tracing Changes\n\nUse cases for tracing changes\n\n#### Use Case 1: Trace the changes of child nodes from the current entity and display the meaningful data from child nodes (composition relation)\n\nModelling in `db/schema.cds`\n\n```cds\nentity Incidents : managed, cuid {\n  ...\n  title          : String @title: 'Title';\n  conversation   : Composition of many Conversation;\n  ...\n}\n\naspect Conversation: managed, cuid {\n    ...\n    message   : String;\n}\n```\n\nAdd the following `@changelog` annotations in `srv/change-tracking.cds`\n\n```cds\nannotate ProcessorService.Incidents with @changelog: [title] {\n  conversation @changelog: [conversation.message];\n}\n```\n\n![CompositionChange](_assets/CompositionChange.png)\n\n#### Use Case 2: Trace the changes of associated entities from the current entity and display the meaningful data from associated entities (association relation)\n\nModelling in `db/schema.cds`\n\n```cds\nentity Incidents : cuid, managed {\n  ...\n  customer       : Association to Customers;\n  title          : String @title: 'Title';\n  ...\n}\n\nentity Customers : cuid, managed {\n  ...\n  email          : EMailAddress;\n  ...\n}\n```\n\nAdd the following `@changelog` annotations in `srv/change-tracking.cds`\n\n```cds\nannotate ProcessorService.Incidents with @changelog: [title] {\n  customer @changelog: [customer.email];\n}\n```\n\n![AssociationChange](_assets/AssociationChange.png)\n\n#### Use Case 3: Trace the changes of fields defined by project customized types and display the meaningful data\n\nModelling in `db/schema.cds`\n\n```cds\ntype StatusType : Association to Status;\n\nentity Incidents : cuid, managed {\n  ...\n  title          : String @title: 'Title';\n  status         : StatusType default 'N';\n  ...\n}\n```\n\nAdd the following `@changelog` annotations in `srv/change-tracking.cds`\n\n```cds\nannotate ProcessorService.Incidents with @changelog: [title] {\n  status   @changelog: [status.code];\n}\n```\n\n![CustomTypeChange](_assets/CustomTypeChange.png)\n\n#### Use Case 4: Trace the changes of chained associated entities from the current entity and display the meaningful data from associated entities (association relation)\n\nModelling in `db/schema.cds`\n\n```cds\nentity Incidents : cuid, managed {\n  ...\n  title          : String @title: 'Title';\n  customer       : Association to Customers;\n  ...\n}\n\nentity Customers : cuid, managed {\n  ...\n  addresses : Association to Addresses;\n  ...\n}\n```\n\nAdd the following `@changelog` annotations in `srv/change-tracking.cds`\n\n```cds\nannotate ProcessorService.Incidents with @changelog: [title] {\n  customer @changelog: [customer.addresses.city, customer.addresses.streetAddress];\n}\n```\n\n![ChainedAssociationChange](_assets/ChainedAssociationChange.png)\n\n\u003e Change-tracking supports analyzing chained associated entities from the current entity in case the entity in consumer applications is a pure relation table. However, the usage of chained associated entities is not recommended due to performance cost.\n\n#### Use Case 5: Trace the changes of union entity and display the meaningful data\n\n`Payable.cds`:\n\n```cds\nentity Payables : cuid {\n    displayId    : String;\n    @changelog\n    name         : String;\n    cryptoAmount : Decimal;\n    fiatAmount   : Decimal;\n};\n```\n\n`Payment.cds`:\n\n```cds\nentity Payments : cuid {\n    displayId : String; //readable ID\n    @changelog\n    name      : String;\n};\n```\n\nUnion entity in `BusinessTransaction.cds`:\n\n```cds\nentity BusinessTransactions          as(\n    select from payments.Payments{\n        key ID,\n            displayId,\n            name,\n            changes  : Association to many ChangeView\n                on changes.objectID = ID AND changes.entity = 'payments.Payments'\n    }\n)\nunion all\n(\n    select from payables.Payables {\n        key ID,\n            displayId,\n            name,\n            changes  : Association to many ChangeView\n               on changes.objectID = ID AND changes.entity = 'payables.Payables'\n    }\n);\n```\n\n![UnionChange.png](_assets/UnionChange.png)\n\n### Don'ts\n\nDon'ts\n\n#### Use Case 1: Don't trace changes for field(s) with `Association to many`\n\n```cds\nentity Customers : cuid, managed {\n  ...\n  incidents : Association to many Incidents on incidents.customer = $self;\n}\n```\n\nThe reason is that: the relationship: `Association to many` is only for modelling purpose and there is no concrete field in database table. In the above sample, there is no column for incidents in the table Customers, but there is a navigation property of incidents in Customers OData entity metadata.\n\n#### Use Case 2: Don't trace changes for field(s) with *Unmanaged Association*\n\n```cds\nentity AggregatedBusinessTransactionData @(cds.autoexpose) : cuid {\n    FootprintInventory: Association to one FootprintInventories\n                        on  FootprintInventory.month                      = month\n                        and FootprintInventory.year                       = year\n                        and FootprintInventory.FootprintInventoryScope.ID = FootprintInventoryScope.ID;\n    ...\n}\n```\n\nThe reason is that: When deploying to relational databases, Associations are mapped to foreign keys. Yet, when mapped to non-relational databases they're just references. More details could be found in [Prefer Managed Associations](https://cap.cloud.sap/docs/guides/domain-models#managed-associations). In the above sample, there is no column for FootprintInventory in the table AggregatedBusinessTransactionData, but there is a navigation property FootprintInventory of in OData entity metadata.\n\n\n## Contributing\n\nThis project is open to feature requests/suggestions, bug reports etc. via [GitHub issues](https://github.com/cap-js/change-tracking/issues). Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](CONTRIBUTING.md).\n\n### Testing changes locally\n\nIn the `tests/bookshop` folder a full sample application is provided, against which you can test your changes:\n\n```sh\ngit clone https://github.com/cap-js/change-tracking\nnpm i\ncd tests/bookshop\ncds watch\n```\n\n## Code of Conduct\n\nWe as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its [Code of Conduct](CODE_OF_CONDUCT.md) at all times.\n\n## Licensing\n\nCopyright 2023 SAP SE or an SAP affiliate company and contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/cap-js/change-tracking).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcap-js%2Fchange-tracking","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcap-js%2Fchange-tracking","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcap-js%2Fchange-tracking/lists"}