Esempio n. 1
0
 /// <summary>
 /// This method decides to insert sample accepted date time for the sample.
 /// </summary>
 /// <param name="insertAR">Analysis request parameters</param>
 /// <returns>true or false indicating whether the sample needs to be collected</returns>
 private bool DecideToMarkSampleAsAccepted(AnalysisRequestDataModel insertAR)
 {
     if (insertAR.SampleReceivedDate.HasValue)
     {
         return(true);
     }
     return(false);
 }
Esempio n. 2
0
        private RequestDataStatus AssesClinicalDetailStatus
            (AnalysisRequestDataModel request, List <ClinicalDetailsDatabaseModel> clinicalDetails)
        {
            var status = RequestDataStatus.New;

            if (!ClinicalDetailsDatabaseModel.AreEqual(request.ClinicalDetails, clinicalDetails))
            {
                status = RequestDataStatus.Dirty;
            }
            else
            {
                status = RequestDataStatus.Clean;
            }

            return(status);
        }
Esempio n. 3
0
        private RequestDataStatus AssesPatientStatus
            (PatientModel patient, AnalysisRequestDataModel request)
        {
            var status = RequestDataStatus.New;

            if (patient != null)
            {
                if (!patient.AreEqual(request))
                {
                    status = RequestDataStatus.Dirty;
                }
                else
                {
                    status = RequestDataStatus.Clean;
                }
            }
            return(status);
        }
Esempio n. 4
0
        public async Task InsertSampleCollectedDate(AnalysisRequestDataModel request, int loggedInUserId)
        {
            var storedProcedure = "[dbo].[usp_UpdateSampleWithCin]";
            var parameters      = new
            {
                Cin            = request.Cin,
                SiteId         = request.SiteId,
                CollectionDate = request.SampleCollectionDate,
                ReceivedDate   = request.SampleReceivedDate,
                UserId         = loggedInUserId
            };

            try
            {
                _ = await SelectInsertOrUpdateAsync <dynamic, dynamic>(storedProcedure, parameters);
            }
            catch (Exception)
            {
                throw;
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Asses the status of request and sample data supplied by
        /// UI compared with that on database
        /// </summary>
        /// <param name="requestAndSample"></param>
        /// <param name="request"></param>
        /// <returns>An enum indicating new, dirty or clean status of supplied data
        /// in comparision with database.
        /// </returns>
        private RequestDataStatus AssesRequestAndSampleStatus
            (RequestAndSampleDatabaseModel requestAndSample, AnalysisRequestDataModel request)
        {
            //Setting an initial status of new
            var status = RequestDataStatus.New;

            if (requestAndSample != null)
            {
                //checks Age, Cin, Site, Collection Date and received date
                if (!requestAndSample.AreEqual(request))
                {
                    status = RequestDataStatus.Dirty;
                    //This will require an update. updates will be done in a later step.
                }
                else
                {
                    status = RequestDataStatus.Clean;
                }
            }

            return(status);
        }
Esempio n. 6
0
        private async Task <bool> InsertNewCompleteRequest
            (int patientId, AnalysisRequestDataModel request, int loggedInUserId)
        {
            var  insertData = new RequestSampleAndClinicalDetailsInsertDatabaseModel(patientId, request, statusDataAccess, loggedInUserId);
            bool success;

            if (string.IsNullOrEmpty(insertData.CommaDelimitedClinicalDetailsIds))
            {
                // when clinical details are not available.
                success = await SelectInsertOrUpdateAsync <bool, dynamic>
                              ("[dbo].[usp_InsertAnalysisRequestSampleAndRequestedTests]", insertData.GetWithoutClinicalDetails());
                await InsertSampleCollectedDate(request, loggedInUserId);

                return(success);
            }
            //with clinical details
            success = await SelectInsertOrUpdateAsync <bool, RequestSampleAndClinicalDetailsInsertDatabaseModel>
                          ("[dbo].[usp_InsertAnalysisRequestClinicalDetailsSampleAndRequestedTests]", insertData);
            await InsertSampleCollectedDate(request, loggedInUserId);

            return(success);
        }
Esempio n. 7
0
        /// <summary>
        /// Determines whether the patient or an existing analysis request is changed to another patient
        /// with current submitted request confirmation. Changing patient to a whole another patient is not allowed, but
        /// updating patient details is allowed except for NationalId / PP
        /// </summary>
        /// <param name="request">user submitted request data via UI</param>
        /// <returns>Returns true if the Nid/Pp does not match with the request of the same CIN on the database</returns>
        private async Task <ExistingRequestsPatientComparisionArgs> IsPatientDifferentForAnalysisRequest
            (AnalysisRequestDataModel request)
        {
            //get database patient details for the CIN
            var patient = await patientData.GetPatientBySamplCin(request.Cin);

            //If no records found on the database for the CIN, return false.
            if (patient is null)
            {
                return(new ExistingRequestsPatientComparisionArgs()
                {
                    IsAnalysisRequestsPatientChanged = false
                });
            }

            //If NidPp matches with the user input, return false.
            if (patient.IsMatch(request))
            {
                return(new ExistingRequestsPatientComparisionArgs()
                {
                    IsAnalysisRequestsPatientChanged = false
                });
            }

            // if none of the above matches, It means that the patient changed to another patient for an existing request.
            //  So return true with database patient data.
            return(new ExistingRequestsPatientComparisionArgs()
            {
                IsAnalysisRequestsPatientChanged = true,
                DatabasePatient = new PatientNidPpAndNameModel()
                {
                    Fullname = patient.Fullname,
                    NidPp = patient.NidPp
                }
            });
        }
Esempio n. 8
0
        public async Task <bool> ConfirmRequestAsync(AnalysisRequestDataModel request, int loggedInUserId, bool isSamplePriority = false)
        {
            RequestDataStatus requestSampleStatus   = RequestDataStatus.New;
            RequestDataStatus patientStatus         = RequestDataStatus.New;
            RequestDataStatus clinicalDetailsStatus = RequestDataStatus.New;
            int InsertedPatientId = 0;

            List <TestsModel> TestsToInsert = new List <TestsModel>();
            List <TestsModel> TestsToRemove = new List <TestsModel>();
            List <ClinicalDetailsDatabaseModel> clinicalDetails         = new List <ClinicalDetailsDatabaseModel>();
            List <ResultsDatabaseModel>         databaseTestsForRequest = new List <ResultsDatabaseModel>();


            #region Request Rejection Criteria - Primary
            //Requests with no Cin are invalid
            if (string.IsNullOrEmpty(request.Cin))
            {
                throw new ArgumentNullException("CIN", "COVID Identification number cannot be null! Analysis request not saved!");
            }
            //Requests with not tests are not valid.
            if (request.Tests.Count == 0)
            {
                throw new ArgumentException("A minimum of one test is mandatory to confirm the request!");
            }
            //Checking whether the current request exists on the database. If it does, any edits for the request should not change the patient to a new patient.
            var PatientDataValidityForAnalysisRequest = await IsPatientDifferentForAnalysisRequest(request);

            //if the data update criteria for existing request fails, throw an exception saying so...
            if (PatientDataValidityForAnalysisRequest.IsAnalysisRequestsPatientChanged)
            {
                throw new Exception("Cannot confirm request. Cannot change patient for a previously confirmed request!\n" +
                                    $"Previous details: {request.Cin}: {PatientDataValidityForAnalysisRequest.DatabasePatient.NidPp} ( {PatientDataValidityForAnalysisRequest.DatabasePatient.Fullname} )\n" +
                                    $"Current details: {request.Cin}: {request.NationalIdPassport} ( {request.Fullname} )");
            }

            #endregion

            #region Fetch Present data
            //load the sample from database, if exists
            var requestAndSample = await GetSampleByIdAsync(request.Cin);

            //fetch patient data specific to the now handlng request
            PatientModel patient = (await patientData.GetPatientByNidPp(request.NationalIdPassport)).FirstOrDefault();

            //if the request and sample exist on the database...
            if (requestAndSample != null)
            {
                //Get clinical details saved on the database for request
                clinicalDetails = await clinicalDetailsData.GetClinicalDetailsByRequestId(requestAndSample.RequestId);

                //Get requested tests saved on the database
                databaseTestsForRequest = await GetRequestedTestsByRequestIdAsync(requestAndSample.RequestId);
            }

            #endregion

            #region Determine request, sample and , clinical details status | Determine Tests to insert / delete
            //Checking whether the current handling request is new, clean, or dirty.
            requestSampleStatus = AssesRequestAndSampleStatus(requestAndSample, request);
            //checking whether the patient for the current request is new, clean or dirty.
            patientStatus = AssesPatientStatus(patient, request);

            //if the request and sample was previously saved on database....
            if (requestAndSample != null)
            {
                //determine the status of clinical details... New, Clean or dirty.
                clinicalDetailsStatus = AssesClinicalDetailStatus(request, clinicalDetails);
                //Generate a list of tests to insert for the request
                TestsToInsert = GetTestsToInsert(request.Tests, databaseTestsForRequest);
                //Make a list of tests for the request that exists on the database but does not exist on the request.
                //NOTE: If no results exists for these tests, they will be removed.
                TestsToRemove = GetTestsToRemove(request.Tests, databaseTestsForRequest);
            }

            #endregion

            #region Insert / Update / Delete from database

            #region Database IO

            #region insert / update patient

            if (patientStatus == RequestDataStatus.Dirty)
            {
                var patientToUpdate = new PatientUpdateDatabaseModel()
                {
                    Id          = patient.Id,
                    Fullname    = request.Fullname,
                    NidPp       = request.NationalIdPassport,
                    Birthdate   = DateHelper.GetCD4FormatJustDateNoTime(request.Birthdate),
                    GenderId    = request.GenderId,
                    AtollId     = request.AtollId,
                    CountryId   = request.CountryId,
                    Address     = request.Address,
                    PhoneNumber = request.PhoneNumber,
                    InstituteAssignedPatientId = request.InstituteAssignedPatientId
                };
                var isPatientUpdated = await patientData.UpdatePatientById(patientToUpdate);

                if (!isPatientUpdated)
                {
                    throw new Exception("Cannot update patient data!");
                }
            }
            if (patientStatus == RequestDataStatus.New)
            {
                //insert patient
                var patientToInsert = new PatientInsertDatabaseModel()
                {
                    Fullname    = request.Fullname,
                    NidPp       = request.NationalIdPassport,
                    Birthdate   = DateHelper.GetCD4FormatJustDateNoTime(request.Birthdate),
                    GenderId    = request.GenderId,
                    AtollId     = request.AtollId,
                    CountryId   = request.CountryId,
                    Address     = request.Address,
                    PhoneNumber = request.PhoneNumber,
                    InstituteAssignedPatientId = request.InstituteAssignedPatientId
                };
                InsertedPatientId = await patientData.InsertPatient(patientToInsert);

                if (InsertedPatientId == 0)
                {
                    throw new Exception("An error occured. Cannot insert the patient!");
                }
            }

            #endregion

            #region Case New Request, Everything below the tree is new, Insert all

            if (requestSampleStatus == RequestDataStatus.New)
            {
                //IF REQUEST IS NEW:: CLINICAL DETAILS, SAMPLE AND REQUESTED TESTS
                //WILL BE NEW FOR SURE. SO HANDLE THEM ALL AT THE SAME TIME
                var output = await InsertNewCompleteRequest(GetPatientId(patient, InsertedPatientId), request, loggedInUserId);
                await InsertUpdateSamplePriorityAsync(request.Cin, isSamplePriority, loggedInUserId);

                return(output);
            }

            #endregion

            #region Update request

            if (requestSampleStatus == RequestDataStatus.Dirty)
            {
                var requestToUpdate = new AnalysisRequestUpdateDatabaseModel()
                {
                    Id            = requestAndSample.RequestId,
                    PatientId     = patient.Id,
                    EpisodeNumber = request.EpisodeNumber,
                    Age           = request.Age
                };
                var isRequestUpdated = await UpdateRequestAsync(requestToUpdate, loggedInUserId);

                if (!isRequestUpdated)
                {
                    throw new Exception("Cannot update request data! [ either episode number, age or patient associated with request was not updated ]");
                }
            }


            #endregion

            #region Update Sample

            if (requestSampleStatus == RequestDataStatus.Dirty)
            {
                var sampleToUpdate = new SampleUpdateDatabaseModel()
                {
                    Cin            = request.Cin,
                    SiteId         = request.SiteId,
                    CollectionDate = request.SampleCollectionDate,
                    ReceivedDate   = request.SampleReceivedDate
                };

                var output = await sampleDataAccess.UpdateSample(sampleToUpdate, loggedInUserId);

                if (!output)
                {
                    throw new Exception("Cannot sample details. [May include: Site, collected date or received date]. Please verify!");
                }
            }

            #endregion

            #region Update Results Table [Test data | NOT ACTUAL SAMPLE RESULTS]

            if (TestsToInsert.Count > 0 || TestsToRemove.Count > 0)
            {
                var output = await resultDataAccess.ManageRequestedTestsDataAsync(TestsToInsert, TestsToRemove, request.Cin, loggedInUserId);

                if (!output)
                {
                    throw new Exception("Error adding or removing requested tests!");
                }
            }

            #endregion

            #region Sync Clinical details data
            if (clinicalDetailsStatus == RequestDataStatus.Dirty)
            {
                //Sync
                string csvClinicalDetails =
                    ClinicalDetailsDataAccess.GetCsvClinicalDetails(request.ClinicalDetails);
                var output = await clinicalDetailsData.SyncClinicalDetails
                                 (csvClinicalDetails, requestAndSample.RequestId);

                if (!output)
                {
                    throw new Exception("Cannot update clinical details for the request.");
                }
            }
            #endregion

            #region Update Sample and Test Priority
            await InsertUpdateSamplePriorityAsync(request.Cin, isSamplePriority, loggedInUserId);

            #endregion

            #endregion


            #endregion

            return(true);
        }
Esempio n. 9
0
        public async Task <Response> Save(AnalysisRequestModel request)
        {
            _logger.LogDebug($"Analysis Request received from Billing.\n{JsonConvert.SerializeObject(request, Formatting.Indented)}");

            //check for the presence of VALID userid of the user who accepted the sample
            if (request.Request.SampleReceivedBy == 0 || request.Request.SampleReceivedBy == 1 || request.Request.SampleReceivedBy == 2 || request.Request.SampleReceivedBy == 3)
            {
                return(new Response()
                {
                    Status = 304, Message = "Required parameter not provided or invalid. [SampleReceivedBy:int]"
                });
            }


            _logger.LogDebug("Building Analysis Request");
            var insertAR = new AnalysisRequestDataModel()
            {
                EpisodeNumber        = request.Request.MemoNumber,
                Cin                  = DeriveSampleNo(request.Patient),
                SiteId               = request.Request.SiteId,
                SampleCollectionDate = GetDatetimeFromTicks(request.Request.SampleCollectedAt),
                SampleReceivedDate   = GetDatetimeFromTicks(request.Request.SampleReceivedAt),
                NationalIdPassport   = request.Patient.NidPp,
                Fullname             = request.Patient.Fullname,
                Birthdate            = GetDatetimeFromTicks(request.Patient.Birthdate),
                Age                  = request.Patient.Age,
                AtollId              = request.Patient.AtollId,
                Address              = request.Patient.Address,
                GenderId             = request.Patient.GenderId,
                PhoneNumber          = request.Patient.PhoneNumber,
                CountryId            = request.Patient.NationalityId,
                Tests                = new List <TestsModel>(),
                ClinicalDetails      = new List <ClinicalDetailsSelectionModel>()
            };

            //try parsing patient Id
            var isPatientIdLong = long.TryParse(request.Patient.PatientId, out var longPatientId);

            if (isPatientIdLong)
            {
                insertAR.InstituteAssignedPatientId = longPatientId;
                _logger.LogInformation($"Patient Id successfully parsed as long. Patient Id: {longPatientId}");
            }
            if (!isPatientIdLong)
            {
                _logger.LogError($"Invalid patient Id. Expected to be numeric long. Actual: {request.Patient.PatientId}");
            }

            var UnmappedTestCodesExist = false;

            _logger.LogDebug("Mapping analyses");
            foreach (var item in request.Analyses.RequestedTests)
            {
                var cd4Tests = GetTestIdFromBillingCode(item);
                if (cd4Tests is null)
                {
                    _logger.LogWarning($"Billing TestCode: {item} not mapped to any CD4 TestCodes"); UnmappedTestCodesExist = true; continue;
                }
                if (cd4Tests.Count == 0)
                {
                    _logger.LogWarning($"Billing TestCode: {item} not mapped to any CD4 TestCodes"); UnmappedTestCodesExist = true; continue;
                }

                insertAR.Tests.AddRange(cd4Tests);
                _logger.LogDebug($"Billing TestCode: {item} mapped to test(s): {JsonConvert.SerializeObject(cd4Tests)}");
            }
            _logger.LogDebug("Mapping analyses completed");


            if (request.Analyses.RequestedTests.Count > 0 && insertAR.Tests.Count == 0)
            {
                _logger.LogInformation("Response code 500 with message None of the test codes are mapped. Analysis request not inserted to CD4");
                return(new Response()
                {
                    Status = 500, Message = "None of the test codes are mapped. Analysis request not inserted to CD4"
                });
            }



            try
            {
                _logger.LogDebug("Calling datalayer for inserting/updating analysis request");
                await _analysisRequestDataAccess.ConfirmRequestAsync(insertAR, 2);

                //ToDo: insert the person who received / accepted the sample
                await _ndaTrackingDataAccess.UpsertSampleReceivedUserIdAsync(insertAR.Cin, request.Request.SampleReceivedBy, 2);

                //insert the sample accepted date and time if required.
                if (DecideToMarkSampleAsAccepted(insertAR))
                {
                    _logger.LogInformation("Inserting sample accepted date and time");
                    await _statusDataAccess.SetSampleAcceptedTimeReceivedFromBilling
                        (insertAR.Cin, insertAR.SampleReceivedDate.Value.ToString("yyyy-MM-dd HH:mm:ss"));
                }

                if (UnmappedTestCodesExist)
                {
                    _logger.LogDebug("Response code 201 with message Some unmapped tests / profiles not inserted to CD4.");
                    return(new Response()
                    {
                        Status = 201, Message = "Some unmapped tests / profiles not inserted to CD4."
                    });
                }

                _logger.LogDebug("Response code 200 with message success.");
                return(new Response()
                {
                    Status = 200, Message = "Success"
                });
            }
            catch (Exception ex)
            {
                _logger.LogDebug($"Response code 500 with message {ex.Message}.");
                return(new Response()
                {
                    Status = 500, Message = ex.Message
                });
            }
        }
Esempio n. 10
0
        public override async Task <Response> Save(AnalysisRequestModel request, ServerCallContext context)
        {
            _logger.LogDebug($"Analysis Request received from Billing.\n{JsonConvert.SerializeObject(request, Formatting.Indented)}");

            _logger.LogDebug("Building Analysis Request");
            var insertAR = new AnalysisRequestDataModel()
            {
                EpisodeNumber        = request.Request.MemoNumber,
                Cin                  = request.Request.SampleId,
                SiteId               = request.Request.SiteId,
                SampleCollectionDate = GetDatetimeFromTicks(request.Request.SampleCollectedDateTime),
                SampleReceivedDate   = GetDatetimeFromTicks(request.Request.SampleReceivedDateTime),
                NationalIdPassport   = request.Patient.NidPp,
                Fullname             = request.Patient.Fullname,
                Birthdate            = GetDatetimeFromTicks(request.Patient.Birthdate),
                Age                  = request.Patient.Age,
                AtollId              = request.Patient.AtollId,
                Address              = request.Patient.Address,
                GenderId             = request.Patient.GenderId,
                PhoneNumber          = request.Patient.PhoneNumber,
                CountryId            = request.Patient.Nationality,
                Tests                = new List <TestsModel>(),
                ClinicalDetails      = new List <ClinicalDetailsSelectionModel>()
            };

            var UnmappedTestCodesExist = false;

            _logger.LogDebug("Mapping analyses");
            foreach (var item in request.Tests.AnalysisId)
            {
                var cd4Tests = GetTestIdFromBillingCode(item);
                if (cd4Tests is null)
                {
                    _logger.LogWarning($"Billing TestCode: {item} not mapped to any CD4 TestCodes"); UnmappedTestCodesExist = true; continue;
                }
                if (cd4Tests.Count == 0)
                {
                    _logger.LogWarning($"Billing TestCode: {item} not mapped to any CD4 TestCodes"); UnmappedTestCodesExist = true; continue;
                }

                insertAR.Tests.AddRange(cd4Tests);
                _logger.LogDebug($"Billing TestCode: {item} mapped to test(s): {JsonConvert.SerializeObject(cd4Tests)}");
            }
            _logger.LogDebug("Mapping analyses completed");


            if (request.Tests.AnalysisId.Count > 0 && insertAR.Tests.Count == 0)
            {
                _logger.LogInformation("Response code 500 with message None of the test codes are mapped. Analysis request not inserted to CD4");
                return(new Response()
                {
                    Status = 500, Message = "None of the test codes are mapped. Analysis request not inserted to CD4"
                });
            }



            try
            {
                _logger.LogDebug("Calling datalayer for inserting/updating analysis request");
                await _analysisRequestDataAccess.ConfirmRequestAsync(insertAR, 1);

                //insert the sample accepted date and time if required.
                if (DecideToMarkSampleAsAccepted(insertAR))
                {
                    _logger.LogInformation("Inserting sample accepted date and time");
                    await _statusDataAccess.SetSampleAcceptedTimeReceivedFromBilling
                        (insertAR.Cin, insertAR.SampleReceivedDate.Value.ToString("yyyy-MM-dd HH:mm:ss"));
                }

                if (UnmappedTestCodesExist)
                {
                    _logger.LogDebug("Response code 201 with message Some unmapped tests / profiles not inserted to CD4.");
                    return(new Response()
                    {
                        Status = 201, Message = "Some unmapped tests / profiles not inserted to CD4."
                    });
                }

                _logger.LogDebug("Response code 200 with message success.");
                return(new Response()
                {
                    Status = 200, Message = "Success"
                });
            }
            catch (Exception ex)
            {
                _logger.LogDebug($"Response code 500 with message {ex.Message}.");
                return(new Response()
                {
                    Status = 500, Message = ex.Message
                });
            }
        }