diff --git a/app/schema/schema.graphql b/app/schema/schema.graphql index 4c54e30c9e..9ad7819c92 100644 --- a/app/schema/schema.graphql +++ b/app/schema/schema.graphql @@ -50871,6 +50871,32 @@ input JSONFilter { notIn: [JSON!] } +"""All input for the `jsonbMinus` mutation.""" +input JsonbMinusInput { + """ + An arbitrary string value with no semantic meaning. Will be included in the + payload verbatim. May be used to track mutations by the client. + """ + clientMutationId: String + minuend: JSON! + subtrahend: JSON! +} + +"""The output of our `jsonbMinus` mutation.""" +type JsonbMinusPayload { + """ + The exact same `clientMutationId` that was provided in the mutation input, + unchanged and unused. May be used by a client to track mutations. + """ + clientMutationId: String + json: JSON + + """ + Our root query field type. Allows us to run any query from our mutation payload. + """ + query: Query +} + type KeycloakJwt { acr: String aud: String @@ -52297,6 +52323,12 @@ type Mutation { """ input: GenerateQuarterlyReportsInput! ): GenerateQuarterlyReportsPayload + jsonbMinus( + """ + The exclusive input argument for this mutation. An object type, make sure to see documentation for this object’s fields. + """ + input: JsonbMinusInput! + ): JsonbMinusPayload stageDirtyFormChanges( """ The exclusive input argument for this mutation. An object type, make sure to see documentation for this object’s fields. @@ -66928,7 +66960,7 @@ type Query implements Node { paymentByRowId(rowId: Int!): Payment """ - returns a form_change for a table in the pending state for the current user, i.e. allows to resume the creation of any table row + returns list of key-value pairs present in the first argument but not the second argument """ pendingNewFormChangeForTable(tableName: String!): FormChange diff --git a/app/schema/schema.json b/app/schema/schema.json index caf884b9ae..0a319f9f41 100644 --- a/app/schema/schema.json +++ b/app/schema/schema.json @@ -171233,6 +171233,102 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "JsonbMinusInput", + "description": "All input for the `jsonbMinus` mutation.", + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "An arbitrary string value with no semantic meaning. Will be included in the\npayload verbatim. May be used to track mutations by the client.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "minuend", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "JSON", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "subtrahend", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "JSON", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "JsonbMinusPayload", + "description": "The output of our `jsonbMinus` mutation.", + "fields": [ + { + "name": "clientMutationId", + "description": "The exact same `clientMutationId` that was provided in the mutation input,\nunchanged and unused. May be used by a client to track mutations.", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "json", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "JSON", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "query", + "description": "Our root query field type. Allows us to run any query from our mutation payload.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "Query", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "KeycloakJwt", @@ -176610,6 +176706,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "jsonbMinus", + "description": null, + "args": [ + { + "name": "input", + "description": "The exclusive input argument for this mutation. An object type, make sure to see documentation for this object’s fields.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "JsonbMinusInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "JsonbMinusPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "stageDirtyFormChanges", "description": null, @@ -229591,7 +229714,7 @@ }, { "name": "pendingNewFormChangeForTable", - "description": "returns a form_change for a table in the pending state for the current user, i.e. allows to resume the creation of any table row", + "description": "returns list of key-value pairs present in the first argument but not the second argument", "args": [ { "name": "tableName", diff --git a/schema/deploy/mutations/commit_form_change_internal.sql b/schema/deploy/mutations/commit_form_change_internal.sql index 2eb823e4d5..eaabad0d50 100644 --- a/schema/deploy/mutations/commit_form_change_internal.sql +++ b/schema/deploy/mutations/commit_form_change_internal.sql @@ -7,6 +7,8 @@ declare recordId int; pending_form_change cif.form_change; parent_of_pending_form_change cif.form_change; + pending_minus_pendings_parent jsonb; + committing_minus_pendings_parent jsonb; begin if fc.validation_errors != '[]' then @@ -48,12 +50,29 @@ begin and form_data_record_id = fc.form_data_record_id limit 1; select * into parent_of_pending_form_change from cif.form_change where id = pending_form_change.previous_form_change_id limit 1; - -- set the pending form change data to be the committing form change data, plus the changes made in the - -- pending revision - update cif.form_change - set new_form_data = - (fc.new_form_data || cif.jsonb_minus(pending_form_change.new_form_data, parent_of_pending_form_change.new_form_data)) - where id = pending_form_change.id; + + select (cif.jsonb_minus(pending_form_change.new_form_data, parent_of_pending_form_change.new_form_data)) + into pending_minus_pendings_parent; + select (cif.jsonb_minus(fc.new_form_data, parent_of_pending_form_change.new_form_data)) + into committing_minus_pendings_parent; + + if committing_minus_pendings_parent is not null then + if pending_minus_pendings_parent is not null then + -- if the committing and pending form changes both have changes from the pending form change's parent, + -- then set the pending form change to be the committing form change, plus the changes made in the penging form change. + update cif.form_change + set new_form_data = + (fc.new_form_data || pending_minus_pendings_parent) + where id = pending_form_change.id; + else + -- The pending form change hasn't made any changes since its creation, but the committing form change has. + -- Set the pending form change ot be the committing form change as it is the latest information + update cif.form_change + set new_form_data = + (fc.new_form_data) + where id = pending_form_change.id; + end if; + end if; elsif fc.operation = 'archive' then delete from cif.form_change