Version History for Custom Fields in Orders and Order Lines
Summary
UIOR-1230: Custom Fields - consider Version historyOpen aims to extend the version history on orders and order lines to include custom fields. Currently, the information that is stored in audit records for orders and order lines is not sufficient to support all outlined requirements.
The requirements are:
The history should display custom fields with their corresponding labels for keys and values, e.g.:
Given the exemplary entry
"customFields": { "membership": "opt_0" }
The key
membership
should display as"Membership"
The select option value
opt_0
should display as"Yes"
If a custom field definition is deleted (via Settings) it should have no effect on already saved versions.
Current state
The version history view for orders and order lines does not display any information on custom fields.
The audit records with elements
orderSnapshot
andorderLineSnapshot
do contain custom fields data, but the custom fields entries contain references to custom field definitions stored elsewhere.
Currently such an audit record may look like this:{ "orderAuditEvents": [ { "id": "a095b07d-94a8-4756-b999-4e5a0dba8be1", "action": "Edit", "orderId": "38cab6c5-4ba9-47f4-8c83-d4c192af8191", "userId": "4f218243-e15e-5a9e-9733-4e2ccd9d95d2", "eventDate": "2024-07-03T07:31:28.463+00:00", "actionDate": "2024-07-03T07:31:28.455+00:00", "orderSnapshot": { "map": { "id": "38cab6c5-4ba9-47f4-8c83-d4c192af8191", "notes": [], "vendor": "e0fb5df2-cdf1-11e8-a8d5-f2801f1b9fd1", "approved": false, "poNumber": "10006", "orderType": "One-Time", "acqUnitIds": [], "reEncumber": true, "customFields": { "externalOrderNumber": "7890" }, "workflowStatus": "Pending" }, "empty": false } } ] }
Custom field definitions are not stored in the audit records, so its currently not possible to resolve custom field values (in the above case, a label for
externalOrderNumber
) to a historic state.The current definition for custom fields is available at the
/custom-fields
endpoint.{ "customFields": [ { "id": "fd725b6f-8723-4003-878e-69ffe255ade7", "name": "External order number", "refId": "externalOrderNumber", "type": "TEXTBOX_SHORT", "entityType": "purchase_order", "visible": true, "required": false, "isRepeatable": false, "order": 1, "helpText": "", "textField": { "fieldFormat": "TEXT" }, "metadata": { "createdDate": "2024-07-03T01:55:13.433+00:00", "updatedDate": "2024-07-03T01:55:13.433+00:00" } }, { "id": "2970f8fc-3ace-441e-b994-879db86e1d52", "name": "Membership", "refId": "membership", "type": "SINGLE_SELECT_DROPDOWN", "entityType": "po_line", "visible": true, "required": false, "isRepeatable": false, "order": 1, "helpText": "", "selectField": { "multiSelect": false, "options": { "values": [ { "id": "opt_1", "value": "No", "default": false }, { "id": "opt_0", "value": "Yes", "default": false } ], "sortingOrder": "CUSTOM" } }, "metadata": { "createdDate": "2024-07-03T01:55:13.455+00:00", "updatedDate": "2024-07-03T01:55:13.455+00:00" } } ], "totalRecords": 2 }
Proposed backend changes
In order to be able to resolve the keys and values of custom fields to their corresponding (historic) labels, the custom fields definition needs to be stored as part of the audit record.
Introduce an additonal attribute
customFieldsSnapshot
to the audit records which contains the definitions of custom fields at the time a change to a order or order line was made:order_audit_event for orders and
order_line_audit_event for order lines
An updated audit record might look like this:
{ "orderAuditEvents": [ { "id": "a095b07d-94a8-4756-b999-4e5a0dba8be1", "action": "Edit", "orderId": "38cab6c5-4ba9-47f4-8c83-d4c192af8191", "userId": "4f218243-e15e-5a9e-9733-4e2ccd9d95d2", "eventDate": "2024-07-03T07:31:28.463+00:00", "actionDate": "2024-07-03T07:31:28.455+00:00", "orderSnapshot": { "map": { "id": "38cab6c5-4ba9-47f4-8c83-d4c192af8191", "notes": [], "vendor": "e0fb5df2-cdf1-11e8-a8d5-f2801f1b9fd1", "approved": false, "poNumber": "10006", "orderType": "One-Time", "acqUnitIds": [], "reEncumber": true, "customFields": { "externalOrderNumber": "7890" }, "workflowStatus": "Pending" }, "empty": false }, "customFieldsSnapshot": [ { "id": "fd725b6f-8723-4003-878e-69ffe255ade7", "name": "External order number", "refId": "externalOrderNumber", "type": "TEXTBOX_SHORT", "entityType": "purchase_order", "visible": true, "required": false, "isRepeatable": false, "order": 1, "helpText": "", "textField": { "fieldFormat": "TEXT" } } ] } ] }
Using the additional information from
customFieldsSnapshot
the custom field values can be resolved and displayed in the version history view. Also, the history view is uneffected by any future changes to custom field defintions.
Adjust the implementation of AuditEventProducer in
mod-orders-storage
to include custom fields definitions into theOrderAuditEvent
.
Proposed frontend changes
Add a component that renders custom fields to <POVersion> and <POLineVersion>
Evaluate if the <ViewCustomFieldsRecord> component from
stripes-smart-components
can be reused for this purposeMay require an option to supply a custom fields definition instead of fetching the current ones
May require an addition for being able to highlight changed values
Modules/Libraries in scope
mod-orders-storage
mod-audit
ui-orders
stripes-smart-components
Problems / Implications :
To prevent inconsistencies between the displayed version history and the actual current version, the proposed changes require triggering the creation of audit records for every entity affected by a custom field definition change – including label changes, display order adjustments and deletions.
Applying the proposed changes will significantly increase the size of audit records.
Audit records are likely to contain the same custom fields information repeatedly.