From 1685c1a9c11e802e466aa40cce0f56d84dbac82d Mon Sep 17 00:00:00 2001 From: "Kasper Fuglsang Christensen (Delegate)" Date: Thu, 5 Dec 2024 12:41:02 +0100 Subject: [PATCH] feat: always add resfinder_version to lims approvals --- app/src/app/analysis/judgement/judgement.tsx | 7 ++++- app/src/sap-client/models/ApprovalRequest.ts | 8 ++++++ .../brokers/request/lims_request_broker.py | 3 ++ openapi_specs/SOFI/SOFI.yaml | 6 ++++ web/openapi_specs/SOFI/SOFI.yaml | 6 ++++ web/src/SAP/generated/models/approval.py | 28 ++++++++++++++++++- .../SAP/generated/models/approval_request.py | 28 ++++++++++++++++++- web/src/SAP/generated/openapi/openapi.yaml | 9 ++++++ .../test/test_approval_controller.py | 5 ++++ .../SAP/src/controllers/ApprovalController.py | 6 +++- web/src/SAP/src/services/queue_service.py | 5 +++- 11 files changed, 106 insertions(+), 5 deletions(-) diff --git a/app/src/app/analysis/judgement/judgement.tsx b/app/src/app/analysis/judgement/judgement.tsx index e0ea1d08..f8777518 100644 --- a/app/src/app/analysis/judgement/judgement.tsx +++ b/app/src/app/analysis/judgement/judgement.tsx @@ -150,10 +150,15 @@ export const Judgement = (props: Props) => { setError(true); } else { const matrix = {}; + const required_values = {}; Object.keys(selection).forEach((key) => { matrix[key] = selection[key].cells; + required_values[key] = {} + required_values[key]["resfinder_version"] = + selection[key].original.resfinder_version ?? ""; }); - doApproval({ matrix }); + + doApproval({ matrix, required_values }); } }, [selection, doApproval, setNeedsApproveNotify, getDependentColumns]); diff --git a/app/src/sap-client/models/ApprovalRequest.ts b/app/src/sap-client/models/ApprovalRequest.ts index 120bed7b..bdc46dc1 100644 --- a/app/src/sap-client/models/ApprovalRequest.ts +++ b/app/src/sap-client/models/ApprovalRequest.ts @@ -30,11 +30,18 @@ export interface ApprovalRequest { * @memberof ApprovalRequest */ matrix: { [key: string]: { [key: string]: ApprovalStatus; }; }; + /** + * + * @type {{ [key: string]: { [key: string]: string; }; }} + * @memberof ApprovalRequest + */ + required_values?: { [key: string]: { [key: string]: string; }; }; } export function ApprovalRequestFromJSON(json: any): ApprovalRequest { return { 'matrix': json['matrix'], + 'required_values': !exists(json, 'required_values') ? undefined : json['required_values'], }; } @@ -44,6 +51,7 @@ export function ApprovalRequestToJSON(value?: ApprovalRequest): any { } return { 'matrix': value.matrix, + 'required_values': value.required_values, }; } diff --git a/bifrost/bifrost_queue_broker/brokers/request/lims_request_broker.py b/bifrost/bifrost_queue_broker/brokers/request/lims_request_broker.py index 318e1489..b757fbde 100644 --- a/bifrost/bifrost_queue_broker/brokers/request/lims_request_broker.py +++ b/bifrost/bifrost_queue_broker/brokers/request/lims_request_broker.py @@ -119,6 +119,9 @@ def approve_fields(self, request): for k, v in fields.items() if reverse_column_mapping.normal_get(k) and v } + # add edge-case columns that always should be sent + mapped_request["ResfinderVersion"] = fields["resfinder_version"] + logging.debug(f"Reverse-mapped request: {mapped_request}") conn_id, lms_cfg = create_lims_conn_config() diff --git a/openapi_specs/SOFI/SOFI.yaml b/openapi_specs/SOFI/SOFI.yaml index 30511dd7..3dbfdb6a 100644 --- a/openapi_specs/SOFI/SOFI.yaml +++ b/openapi_specs/SOFI/SOFI.yaml @@ -1031,6 +1031,12 @@ components: properties: matrix: $ref: "#/components/schemas/ApprovalMatrix" + required_values: + type: object + additionalProperties: + type: object + additionalProperties: + type: string Approval: allOf: diff --git a/web/openapi_specs/SOFI/SOFI.yaml b/web/openapi_specs/SOFI/SOFI.yaml index 30511dd7..3dbfdb6a 100644 --- a/web/openapi_specs/SOFI/SOFI.yaml +++ b/web/openapi_specs/SOFI/SOFI.yaml @@ -1031,6 +1031,12 @@ components: properties: matrix: $ref: "#/components/schemas/ApprovalMatrix" + required_values: + type: object + additionalProperties: + type: object + additionalProperties: + type: string Approval: allOf: diff --git a/web/src/SAP/generated/models/approval.py b/web/src/SAP/generated/models/approval.py index eb37c961..843025ee 100644 --- a/web/src/SAP/generated/models/approval.py +++ b/web/src/SAP/generated/models/approval.py @@ -23,11 +23,13 @@ class Approval(Model): Do not edit the class manually. """ - def __init__(self, matrix=None, id=None, approver=None, timestamp=None, sequence_ids=None, status=None): # noqa: E501 + def __init__(self, matrix=None, required_values=None, id=None, approver=None, timestamp=None, sequence_ids=None, status=None): # noqa: E501 """Approval - a model defined in OpenAPI :param matrix: The matrix of this Approval. # noqa: E501 :type matrix: Dict[str, Dict[str, ApprovalStatus]] + :param required_values: The required_values of this Approval. # noqa: E501 + :type required_values: Dict[str, Dict[str, str]] :param id: The id of this Approval. # noqa: E501 :type id: str :param approver: The approver of this Approval. # noqa: E501 @@ -41,6 +43,7 @@ def __init__(self, matrix=None, id=None, approver=None, timestamp=None, sequence """ self.openapi_types = { 'matrix': Dict[str, Dict[str, ApprovalStatus]], + 'required_values': Dict[str, Dict[str, str]], 'id': str, 'approver': str, 'timestamp': datetime, @@ -50,6 +53,7 @@ def __init__(self, matrix=None, id=None, approver=None, timestamp=None, sequence self.attribute_map = { 'matrix': 'matrix', + 'required_values': 'required_values', 'id': 'id', 'approver': 'approver', 'timestamp': 'timestamp', @@ -58,6 +62,7 @@ def __init__(self, matrix=None, id=None, approver=None, timestamp=None, sequence } self._matrix = matrix + self._required_values = required_values self._id = id self._approver = approver self._timestamp = timestamp @@ -98,6 +103,27 @@ def matrix(self, matrix): self._matrix = matrix + @property + def required_values(self): + """Gets the required_values of this Approval. + + + :return: The required_values of this Approval. + :rtype: Dict[str, Dict[str, str]] + """ + return self._required_values + + @required_values.setter + def required_values(self, required_values): + """Sets the required_values of this Approval. + + + :param required_values: The required_values of this Approval. + :type required_values: Dict[str, Dict[str, str]] + """ + + self._required_values = required_values + @property def id(self): """Gets the id of this Approval. diff --git a/web/src/SAP/generated/models/approval_request.py b/web/src/SAP/generated/models/approval_request.py index efa3a126..dfb79331 100644 --- a/web/src/SAP/generated/models/approval_request.py +++ b/web/src/SAP/generated/models/approval_request.py @@ -19,21 +19,26 @@ class ApprovalRequest(Model): Do not edit the class manually. """ - def __init__(self, matrix=None): # noqa: E501 + def __init__(self, matrix=None, required_values=None): # noqa: E501 """ApprovalRequest - a model defined in OpenAPI :param matrix: The matrix of this ApprovalRequest. # noqa: E501 :type matrix: Dict[str, Dict[str, ApprovalStatus]] + :param required_values: The required_values of this ApprovalRequest. # noqa: E501 + :type required_values: Dict[str, Dict[str, str]] """ self.openapi_types = { 'matrix': Dict[str, Dict[str, ApprovalStatus]], + 'required_values': Dict[str, Dict[str, str]], } self.attribute_map = { 'matrix': 'matrix', + 'required_values': 'required_values', } self._matrix = matrix + self._required_values = required_values @classmethod def from_dict(cls, dikt): @@ -68,3 +73,24 @@ def matrix(self, matrix): raise ValueError("Invalid value for `matrix`, must not be `None`") # noqa: E501 self._matrix = matrix + + @property + def required_values(self): + """Gets the required_values of this ApprovalRequest. + + + :return: The required_values of this ApprovalRequest. + :rtype: Dict[str, Dict[str, str]] + """ + return self._required_values + + @required_values.setter + def required_values(self, required_values): + """Sets the required_values of this ApprovalRequest. + + + :param required_values: The required_values of this ApprovalRequest. + :type required_values: Dict[str, Dict[str, str]] + """ + + self._required_values = required_values diff --git a/web/src/SAP/generated/openapi/openapi.yaml b/web/src/SAP/generated/openapi/openapi.yaml index 90ab2a6b..2b7a280a 100644 --- a/web/src/SAP/generated/openapi/openapi.yaml +++ b/web/src/SAP/generated/openapi/openapi.yaml @@ -1215,6 +1215,9 @@ components: type: object ApprovalRequest: example: + required_values: + key: + key: required_values matrix: key: key: matrix @@ -1225,6 +1228,12 @@ components: $ref: '#/components/schemas/ApprovalStatus' type: object type: object + required_values: + additionalProperties: + additionalProperties: + type: string + type: object + type: object required: - matrix type: object diff --git a/web/src/SAP/generated/test/test_approval_controller.py b/web/src/SAP/generated/test/test_approval_controller.py index 5209379c..c4006a3f 100644 --- a/web/src/SAP/generated/test/test_approval_controller.py +++ b/web/src/SAP/generated/test/test_approval_controller.py @@ -34,6 +34,11 @@ def test_create_approval(self): """ body = { + "required_values" : { + "key" : { + "key" : "required_values" + } + }, "matrix" : { "key" : { "key" : "matrix" diff --git a/web/src/SAP/src/controllers/ApprovalController.py b/web/src/SAP/src/controllers/ApprovalController.py index 5360a599..a63b6fa7 100644 --- a/web/src/SAP/src/controllers/ApprovalController.py +++ b/web/src/SAP/src/controllers/ApprovalController.py @@ -44,6 +44,7 @@ def create_approval(user, token_info, body: ApprovalRequest): appr = Approval() appr.matrix = body.matrix + appr.required_values = body.required_values appr.approver = user appr.timestamp = datetime.datetime.now() appr.status = "submitted" @@ -82,6 +83,7 @@ def create_approval(user, token_info, body: ApprovalRequest): for f in time_fields: analysis_timestamp_reverts[error_seq_id] = {f: None} del appr.matrix[error_seq_id] + del appr.required_values[error_seq_id] errors.append(error) # If any sequences errored out on the metadata service, revert their @@ -101,7 +103,9 @@ def create_approval(user, token_info, body: ApprovalRequest): def handle_approvals(approvals: Approval, institution: str): errors = [] for sequence_id, field_mask in approvals.matrix.items(): - if error := post_and_await_approval(sequence_id, field_mask, institution): + if sequence_id in approvals.required_values: + required_values = approvals.required_values[sequence_id] + if error := post_and_await_approval(sequence_id, field_mask, institution, required_values): errors.append(error) return errors diff --git a/web/src/SAP/src/services/queue_service.py b/web/src/SAP/src/services/queue_service.py index ad55d226..6b16995c 100644 --- a/web/src/SAP/src/services/queue_service.py +++ b/web/src/SAP/src/services/queue_service.py @@ -35,7 +35,7 @@ def post_and_await_reload(isolate_id, institution): return {"error": f"Could not reload isolate {isolate_id} due to an error."}, 500 -def post_and_await_approval(sequence_id, field_mask, user_institution): +def post_and_await_approval(sequence_id, field_mask, user_institution, required_values): data = get_analysis_with_metadata(sequence_id) internal_fields = internal_approval_fields() @@ -51,6 +51,9 @@ def post_and_await_approval(sequence_id, field_mask, user_institution): # For LIMS, date_analysis_sofi should always be implicitly included if institution == "FVST": fields["date_analysis_sofi"] = data.get("date_analysis_sofi") + + for field, val in required_values.items(): + fields[field] = val print(data, file=sys.stderr) # TODO UNDO