/// <summary> /// Send email notification after Response /// Emails sent to Group of the release and all Power Users /// </summary> /// <param name="rspDTO"></param> /// <param name="releaseDTO"></param> internal void EmailResponse(WorkflowRequest_DTO requestDTO, WorkflowResponse_DTO rspDTO, Release_DTO releaseDTO) { eMail email = new eMail(); Account_BSO aBso = new Account_BSO(); ADO_readerOutput recipients = new ADO_readerOutput(); string subject = ""; string body = ""; string releaseUrl = getReleaseUrl(releaseDTO); string rqsvalue = Label.Get("workflow.request." + requestDTO.RqsValue); switch (rspDTO.RspCode) { case Constants.C_WORKFLOW_STATUS_APPROVE: //Send the email to power users only recipients = aBso.getUsersOfPrivilege(Resources.Constants.C_SECURITY_PRIVILEGE_POWER_USER); subject = string.Format(Label.Get("email.subject.response-approve"), releaseDTO.MtrCode, releaseDTO.RlsVersion, releaseDTO.RlsRevision); body = string.Format(Label.Get("email.body.response-approve"), rqsvalue, releaseDTO.MtrCode, releaseDTO.RlsVersion, releaseDTO.RlsRevision, releaseUrl, rspDTO.ResponseAccount.CcnEmail, rspDTO.ResponseAccount.CcnUsername, rspDTO.ResponseAccount.CcnName); break; case Constants.C_WORKFLOW_STATUS_REJECT: //Send the email to recipients = aBso.getReleaseUsers(releaseDTO.RlsCode, false); subject = string.Format(Label.Get("email.subject.response-reject"), releaseDTO.MtrCode, releaseDTO.RlsVersion, releaseDTO.RlsRevision); body = string.Format(Label.Get("email.body.response-reject"), rqsvalue, releaseDTO.MtrCode, releaseDTO.RlsVersion, releaseDTO.RlsRevision, releaseUrl, rspDTO.ResponseAccount.CcnEmail, rspDTO.ResponseAccount.CcnUsername, rspDTO.ResponseAccount.CcnName); break; } List <string> allEmails = new List <string>(); allEmails.AddRange(getEmailAddresses(recipients)); if (allEmails.Count == 0) { return; } foreach (string person in allEmails) { email.Bcc.Add(person); } sendMail(email, Configuration_BSO.GetCustomConfig("title"), subject, body); email.Dispose(); }
internal JSONRPC_Output WorkflowSignoffCreate(ADO Ado, WorkflowSignoff_DTO DTO, string SamAccountName) { JSONRPC_Output response = new JSONRPC_Output(); ADO_readerOutput moderators = new ADO_readerOutput(); ADO_readerOutput powerUsers = new ADO_readerOutput(); var adoWorkflowRequest = new WorkflowRequest_ADO(); var adoWorkflowResponse = new WorkflowResponse_ADO(); Release_DTO dtoWip = null; if (!adoWorkflowResponse.IsInUse(Ado, DTO)) // is current workflow -- this should be the response!! { //No Live workflow found so we can't proceed Log.Instance.Debug("No Current workflow response found for this Release Code"); response.error = Label.Get("error.create"); return(response); } //Is this awaiting signoff? var adoWorkflow = new Workflow_ADO(); ADO_readerOutput resultStatus = adoWorkflow.ReadAwaitingSignoff(Ado, SamAccountName, DTO.RlsCode, Configuration_BSO.GetCustomConfig(ConfigType.global, "language.iso.code")); if (!resultStatus.hasData) { //Release not awaiting signoff so we can't proceed Log.Instance.Debug("Release not in status Awaiting Signoff"); response.error = Label.Get("error.update"); return(response); } Security.ActiveDirectory_DTO signoffUser = new Security.ActiveDirectory_DTO() { CcnUsername = SamAccountName }; Security.ActiveDirectory_ADO accAdo = new Security.ActiveDirectory_ADO(); Security.Account_DTO_Read accDto = new Security.Account_DTO_Read() { CcnUsername = signoffUser.CcnUsername }; DTO.SignoffAccount = accAdo.GetUser(Ado, accDto); var adoSignoff = new WorkflowSignoff_ADO(); //Create a comment var adoComment = new Comment_ADO(); int commentCode = adoComment.Create(Ado, DTO, SamAccountName); if (commentCode == 0) { // Can't create a comment so we can't proceed Log.Instance.Debug("Can't create a comment "); response.error = Label.Get("error.create"); return(response); } DTO.CmmCode = commentCode; //We must read the Request and in order to see how we are going to proceed WorkflowRequest_ADO adoWrq = new WorkflowRequest_ADO(); List <WorkflowRequest_DTO> dtoWrqList = adoWrq.Read(Ado, DTO.RlsCode, true); if (dtoWrqList.Count > 1) { //Multiple requests found for this release Log.Instance.Debug("More than one request found for this release "); response.error = Label.Get("error.create"); return(response); } //there must be exactly one live Workflow request at this point WorkflowRequest_DTO dtoWrq = dtoWrqList.Find(x => x.RqsCode != null); //Get the current Release Release_ADO adoRelease = new Release_ADO(Ado); Release_DTO dtoRelease = Release_ADO.GetReleaseDTO(adoRelease.Read(DTO.RlsCode, SamAccountName)); if (dtoRelease == null) { Log.Instance.Debug("Release not found"); response.error = Label.Get("error.create"); return(response); } Account_BSO aBso = new Account_BSO(Ado); moderators = aBso.getReleaseUsers(DTO.RlsCode, null); powerUsers = aBso.getUsersOfPrivilege(Constants.C_SECURITY_PRIVILEGE_POWER_USER); //Is this a Reject? if (DTO.SgnCode.Equals(Constants.C_WORKFLOW_STATUS_REJECT)) { int res = adoSignoff.Create(Ado, DTO, SamAccountName); if (res == 0) { //Can't create a Workflow Signoff so we can't proceed Log.Instance.Debug("Can't create a Workflow Signoff "); response.error = Label.Get("error.create"); return(response); } WorkflowRequest_DTO_Update dtoReq = new WorkflowRequest_DTO_Update(DTO.RlsCode); dtoReq.WrqCurrentFlag = false; //update the request int reqUpdate = adoWorkflowRequest.Update(Ado, dtoReq, SamAccountName); if (reqUpdate == 0) { //Can't save the Request so we can't proceed Log.Instance.Debug("Can't save the Workflow Request"); response.error = Label.Get("error.update"); return(response); } DTO.MtrCode = dtoRelease.MtrCode; // we need this to see which cache we must flush response.data = JSONRPC.success; Email_BSO_NotifyWorkflow notifyReject = new Email_BSO_NotifyWorkflow(); try { notifyReject.EmailSignoff(dtoWrq, DTO, dtoRelease, moderators, powerUsers); } catch { } return(response); } //Not a Reject so we proceed... switch (dtoWrq.RqsCode) { case Constants.C_WORKFLOW_REQUEST_PUBLISH: if (String.IsNullOrEmpty(dtoRelease.PrcCode)) { //There must be a valid product for this release Log.Instance.Debug("No product found for the release "); response.error = Label.Get("error.publish"); return(response); } //Update the current release LiveDatetimeTo to the request Date time dtoRelease.RlsLiveDatetimeFrom = dtoWrq.WrqDatetime; //set the release live flag //update the release version and set the current revision to 0 DateTime switchDate; switchDate = DateTime.Now > dtoWrq.WrqDatetime ? DateTime.Now : dtoWrq.WrqDatetime; dtoRelease.RlsVersion++; dtoRelease.RlsRevision = 0; dtoRelease.RlsLiveFlag = true; dtoRelease.RlsExceptionalFlag = dtoWrq.WrqExceptionalFlag != null ? dtoWrq.WrqExceptionalFlag.Value : false; dtoRelease.RlsReservationFlag = dtoWrq.WrqReservationFlag != null ? dtoWrq.WrqReservationFlag.Value : false; dtoRelease.RlsArchiveFlag = dtoWrq.WrqArchiveFlag != null ? dtoWrq.WrqArchiveFlag.Value : false; dtoRelease.RlsExperimentalFlag = dtoWrq.WrqExperimentalFlag != null ? dtoWrq.WrqExperimentalFlag.Value : false; dtoRelease.RlsLiveDatetimeFrom = switchDate; //get the current live release Release_DTO releaseDTONow = Release_ADO.GetReleaseDTO(adoRelease.ReadLiveNow(DTO.RlsCode)); //Save the changes for the release we're changing int update = adoRelease.Update(dtoRelease, SamAccountName); if (update == 0) { Log.Instance.Debug("Can't update the Release, RlsCode:" + dtoRelease.RlsCode); response.error = Label.Get("error.update"); return(response); } if (releaseDTONow != null) { //...if there is a previous release if (releaseDTONow.RlsCode != 0) { //Update the Live LiveDatetimeTo to the request Datetime releaseDTONow.RlsLiveDatetimeTo = switchDate; //Save the changes for the previous release adoRelease.Update(releaseDTONow, SamAccountName); } } break; case Constants.C_WORKFLOW_REQUEST_PROPERTY: //update release to transfer all flag values from the request to the release dtoRelease.RlsReservationFlag = dtoWrq.WrqReservationFlag != null ? dtoWrq.WrqReservationFlag.Value : false; dtoRelease.RlsArchiveFlag = dtoWrq.WrqArchiveFlag != null ? dtoWrq.WrqArchiveFlag.Value : false; dtoRelease.RlsExperimentalFlag = dtoWrq.WrqExperimentalFlag != null ? dtoWrq.WrqExperimentalFlag.Value : false; //Save the release int updateCount = adoRelease.Update(dtoRelease, SamAccountName); if (updateCount == 0) { //Update of Release failed Log.Instance.Debug("Can't update the Release, RlsCode:" + DTO.RlsCode); response.error = Label.Get("error.update"); return(response); } //if there is a WIP or a pending live associated with this matrix then we need to update the WIP/Pending Live as well: Release_BSO rBso = new Release_BSO(Ado); dynamic wipForLive = rBso.GetWipForLive(dtoRelease.RlsCode, SamAccountName); if (wipForLive == null) { wipForLive = rBso.GetPendingLiveForLive(dtoRelease.RlsCode, SamAccountName); } if (wipForLive != null) { //if a workflow exists for wipForLive, then we must update the flags on that workflow as well var wfForLive = adoWorkflowRequest.Read(Ado, wipForLive.RlsCode, true); if (wfForLive != null) { if (wfForLive.Count > 0) { adoWorkflowRequest.Update(Ado, new WorkflowRequest_DTO_Update() { RlsCode = wipForLive.RlsCode, WrqArchiveFlag = dtoWrq.WrqArchiveFlag, WrqCurrentFlag = true, WrqExperimentalFlag = dtoWrq.WrqExperimentalFlag, WrqReservationFlag = dtoWrq.WrqReservationFlag }, SamAccountName); } } dtoWip = Release_ADO.GetReleaseDTO(adoRelease.Read(wipForLive.RlsCode, SamAccountName)); dtoWip.RlsReservationFlag = dtoRelease.RlsReservationFlag; dtoWip.RlsArchiveFlag = dtoRelease.RlsArchiveFlag; dtoWip.RlsExperimentalFlag = dtoRelease.RlsExperimentalFlag; if (adoRelease.Update(dtoWip, SamAccountName) == 0) { Log.Instance.Debug("Failed to update associated WIP " + dtoWip.MtrCode + " " + dtoWip.RlsVersion + '.' + dtoWip.RlsRevision); } //if this wip has a workflow request, then the workflow request details must also be updated List <WorkflowRequest_DTO> wfList = adoWrq.Read(Ado, dtoWip.RlsCode, true); if (wfList.Count > 0) { foreach (var wf in wfList) { wf.WrqReservationFlag = dtoWrq.WrqReservationFlag; wf.WrqArchiveFlag = dtoWrq.WrqArchiveFlag; wf.WrqExperimentalFlag = dtoWrq.WrqExperimentalFlag; adoWrq.Update(Ado, new WorkflowRequest_DTO_Update() { RlsCode = wf.RlsCode, WrqCurrentFlag = dtoWrq.WrqCurrentFlag, WrqArchiveFlag = dtoWrq.WrqArchiveFlag, WrqExperimentalFlag = dtoWrq.WrqExperimentalFlag, WrqReservationFlag = dtoWrq.WrqReservationFlag }, SamAccountName); } } } break; case Constants.C_WORKFLOW_REQUEST_DELETE: //We can't soft delete the release just yet. We need it to be live until the Request is updated. break; case Constants.C_WORKFLOW_REQUEST_ROLLBACK: //Delete the future release if it exists and set the current to_date to null //Otherwise delete the current release and make the previous release current by setting its to_date to null if (adoRelease.IsLiveNext(dtoRelease.RlsCode)) //this is a future release so get the previous release to roll back to (even if that previous is now historical) { Compare_ADO cAdo = new Compare_ADO(Ado); Release_DTO dtoNowRelease = Release_ADO.GetReleaseDTO(adoRelease.Read(cAdo.ReadPreviousRelease(DTO.RlsCode), SamAccountName)); dtoNowRelease.RlsLiveDatetimeTo = default(DateTime); int rows = adoRelease.Update(dtoNowRelease, SamAccountName); if (rows == 0) { Log.Instance.Debug("Can't update the Release, RlsCode:" + dtoNowRelease.RlsCode); response.error = Label.Get("error.update"); return(response); } //As things stand, dtoRelease is the requested Release (which is a Live Next). This will be deleted in the Delete section below } else { //This isn't a future release - it had better be a Live Now (with a previous) if (!adoRelease.IsLiveNow(dtoRelease.RlsCode)) { //If the request is neither a Live Now release then there's a problem Log.Instance.Debug("Can't delete the Release, RlsCode:" + dtoRelease.RlsCode + ". Release is not current live"); response.error = Label.Get("error.delete"); return(response); } //Find the release that we're trying to rollback to Release_DTO dtoPrevious = Release_ADO.GetReleaseDTO(adoRelease.ReadLivePrevious(dtoRelease.RlsCode)); if (dtoPrevious.RlsCode == 0) { //Previous release not found //You can't roll back unless there's something to roll back to, so... Log.Instance.Debug("Can't delete the Release, RlsCode:" + dtoRelease.RlsCode + ". Release is not current live"); response.error = Label.Get("error.delete"); return(response); } //We set the DatetimeTo to null in the previous release dtoPrevious.RlsLiveDatetimeTo = default(DateTime); int rows = adoRelease.Update(dtoPrevious, SamAccountName); if (rows == 0) { Log.Instance.Debug("Can't update the Release, RlsCode:" + dtoPrevious.RlsCode); response.error = Label.Get("error.update"); return(response); } //Do the rollback of the current release dtoRelease.RlsVersion = dtoPrevious.RlsVersion; dtoRelease.RlsLiveDatetimeFrom = default(DateTime); rows = adoRelease.Update(dtoRelease, SamAccountName); if (rows == 0) { Log.Instance.Debug("Can't update the Release, RlsCode:" + dtoRelease.RlsCode); response.error = Label.Get("error.update"); return(response); } adoRelease.IncrementRevision(dtoRelease.RlsCode, SamAccountName); } break; default: response.error = Label.Get("error.update"); return(response); } int signoffID = adoSignoff.Create(Ado, DTO, SamAccountName); if (signoffID == 0) { //Can't create a Workflow Signoff so we can't proceed Log.Instance.Debug("Can't create a Workflow Signoff "); response.error = Label.Get("error.create"); return(response); } //In all cases, if we have reached this stage, we must update the request to make it non-current WorkflowRequest_DTO_Update dtoRequest = new WorkflowRequest_DTO_Update(DTO.RlsCode); dtoRequest.WrqCurrentFlag = false; //save the request int updated = adoWorkflowRequest.Update(Ado, dtoRequest, SamAccountName); if (updated == 0) { //Can't save the Request so we can't proceed Log.Instance.Debug("Can't save the Workflow Signoff"); response.error = Label.Get("error.update"); return(response); } // We may now proceed with the soft delete Release_BSO_Delete bsoDelete = new Release_BSO_Delete(); System.Navigation.Keyword_Release_ADO krbAdo = new System.Navigation.Keyword_Release_ADO(); switch (dtoWrq.RqsCode) { case Constants.C_WORKFLOW_REQUEST_DELETE: //Soft delete the Release. We had to hold this over to last because the Request updates wouldn't work without a live Release dtoRelease.RlsCode = DTO.RlsCode; Request_ADO adoRequest = new Request_ADO(); if (adoRelease.IsLiveNow(dtoRelease.RlsCode)) { Release_DTO dtoNowRelease = Release_ADO.GetReleaseDTO(adoRelease.ReadLiveNow(dtoRequest.RlsCode)); //Set the toDate to now, thus setting the release to historical if (dtoNowRelease != null) { dtoNowRelease.RlsLiveDatetimeTo = DateTime.Now; int updateCount = adoRelease.Update(dtoNowRelease, SamAccountName); if (updateCount == 0) { Log.Instance.Debug("Can't update the Release, RlsCode:" + dtoNowRelease.RlsCode); response.error = Label.Get("error.update"); return(response); } } //Delete the search keywords for this release krbAdo.Delete(Ado, DTO.RlsCode, null, true); } else if (adoRelease.IsLiveNext(dtoRelease.RlsCode) || adoRelease.IsWip(dtoRelease.RlsCode)) { //Find the previous list if it exists Compare_ADO cAdo = new Compare_ADO(Ado); Release_DTO dtoPreviousRelease = Release_ADO.GetReleaseDTO(adoRelease.Read(cAdo.ReadPreviousRelease(DTO.RlsCode), SamAccountName)); //if there is a previous live set it to historical, but not if we're deleting a WIP if (dtoPreviousRelease != null && !adoRelease.IsWip(dtoRelease.RlsCode)) { //Delete the search keywords for the previous release krbAdo.Delete(Ado, dtoPreviousRelease.RlsCode, null, true); dtoPreviousRelease.RlsLiveDatetimeTo = DateTime.Now; int updateCount = adoRelease.Update(dtoPreviousRelease, SamAccountName); if (updateCount == 0) { Log.Instance.Debug("Can't update the Release, RlsCode:" + dtoPreviousRelease.RlsCode); response.error = Label.Get("error.update"); return(response); } } //Delete the search keywords for this release krbAdo.Delete(Ado, DTO.RlsCode, null, true); // We may now proceed with the soft delete if (bsoDelete.Delete(Ado, DTO.RlsCode, SamAccountName, true) == 0) { Log.Instance.Debug("Can't delete the Release, RlsCode:" + DTO.RlsCode); response.error = Label.Get("error.delete"); return(response); } } else { //Only LiveNow, LiveNext and WIP releases can be deleted. Anything else means there's a problem. Log.Instance.Debug("Can't delete the Release - invalid release status, RlsCode:" + DTO.RlsCode); response.error = Label.Get("error.delete"); return(response); } break; case Constants.C_WORKFLOW_REQUEST_ROLLBACK: //First, if there is a WIP ahead of this live release then that WIP must be deleted Release_ADO releaseAdo = new Release_ADO(Ado); var releaseDTORead = new Release_DTO_Read() { MtrCode = dtoRelease.MtrCode }; var latestRelease = releaseAdo.ReadLatest(releaseDTORead); if (latestRelease != null) { if (dtoRelease.RlsCode != latestRelease.RlsCode) { if (bsoDelete.Delete(Ado, latestRelease.RlsCode, SamAccountName, true) == 0) { Log.Instance.Debug("Can't delete the Release, RlsCode:" + latestRelease.RlsCode); response.error = Label.Get("error.delete"); return(response); } } } // Only Live Next gets soft deleted, while Live Now is turned historical above if (adoRelease.IsLiveNext(dtoRelease.RlsCode)) { if (bsoDelete.Delete(Ado, DTO.RlsCode, SamAccountName, true) == 0) { Log.Instance.Debug("Can't delete the Release, RlsCode:" + DTO.RlsCode); response.error = Label.Get("error.delete"); return(response); } //Delete the search keywords for this release krbAdo.Delete(Ado, DTO.RlsCode, null, true); } // Delete the requested release (it may have been live but may also have been demoted to WIP by now) if (adoRelease.IsWip(dtoRelease.RlsCode)) { if (bsoDelete.Delete(Ado, dtoRelease.RlsCode, SamAccountName, true) == 0) { Log.Instance.Debug("Can't delete the Release, RlsCode:" + dtoRelease.RlsCode); response.error = Label.Get("error.delete"); return(response); } //Delete the search keywords for this release krbAdo.Delete(Ado, DTO.RlsCode, null, true); } break; } DTO.MtrCode = dtoRelease.MtrCode; // we need this to see which cache we must flush response.data = JSONRPC.success; Email_BSO_NotifyWorkflow notify = new Email_BSO_NotifyWorkflow(); var sendMailThread = new Thread(() => { //If an email error occurs, just ignore it and continue as before try { notify.EmailSignoff(dtoWrq, DTO, dtoRelease, moderators, powerUsers); } catch { } }); sendMailThread.Start(); // Clean up caching MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_COMPARE_READ_ADDITION + DTO.RlsCode); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_COMPARE_READ_DELETION + DTO.RlsCode); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_COMPARE_READ_AMENDMENT + DTO.RlsCode); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_CUBE_READ_PRE_DATASET + DTO.RlsCode); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_CUBE_READ_PRE_METADATA + DTO.RlsCode); if (dtoWip != null) { MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_COMPARE_READ_ADDITION + dtoWip.RlsCode); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_COMPARE_READ_DELETION + dtoWip.RlsCode); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_COMPARE_READ_AMENDMENT + dtoWip.RlsCode); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_CUBE_READ_PRE_DATASET + dtoWip.RlsCode); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_CUBE_READ_PRE_METADATA + dtoWip.RlsCode); } MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_NAVIGATION_SEARCH); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_NAVIGATION_READ); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_CUBE_READ_COLLECTION); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_CUBE_READ_DATASET + DTO.MtrCode); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_CUBE_READ_DATASET + DTO.MtrCode); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_CUBE_READ_METADATA + DTO.MtrCode); MemCacheD.CasRepositoryFlush(Resources.Constants.C_CAS_DATA_CUBE_READ_COLLECTION_PXAPI); return(response); }