Skip to content

Commit

Permalink
Merge pull request #1323 from DFE-Digital/create-case-delete-button
Browse files Browse the repository at this point in the history
Create case delete button
  • Loading branch information
FrostyApeOne authored Jul 30, 2024
2 parents 582fdf1 + 7355219 commit bdce560
Show file tree
Hide file tree
Showing 133 changed files with 4,606 additions and 5,346 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace ConcernsCaseWork.API.Contracts.Case
{
public enum CloseCaseError
public enum CaseValidationError
{
Concern = 1,
CaseAction = 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public enum CasePermission
{
None = 0,
View = 1,
Edit = 2
Edit = 2,
EditAndDelete = 3
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,10 @@ public bool HasEditPermissions()
{
return Permissions.Contains(CasePermission.Edit);
}

public bool HasDeletePermissions()
{
return Permissions.Contains(CasePermission.EditAndDelete);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ public async Task When_Delete_CaseWithConcernAndAllCaseActions_Returns_BadReques

//Assert
result.StatusCode.Should().Be(HttpStatusCode.BadRequest);
error.Should().Contain("Cannot deleted Case. Case has related concern(s) and case actions");
error.Should().Contain("Cannot deleted Case. Case has related concern(s) or case actions");
}

[Fact]
Expand All @@ -550,23 +550,6 @@ public async Task When_Delete_CaseWithConcernAndNoCaseActions_Returns_BadRequest
error.Should().Contain("Cannot deleted Case. Case has related concern(s)");
}

[Fact]
public async Task When_Delete_CaseWithNoConcernAndAllCaseActions_Returns_BadRequest()
{
//Arrange
var createCaseRequest = CreateConcernCaseCreateRequest();
var createResult = await CreateConcernCase(createCaseRequest);
CreateAllCaseActionCase(createResult.Urn);

//Act
var result = await _client.DeleteAsync(Delete.DeleteCase(createResult.Urn));
string error = await result.Content.ReadAsStringAsync();

//Assert
result.StatusCode.Should().Be(HttpStatusCode.BadRequest);
error.Should().Contain("Cannot deleted Case. Case has related case actions");
}

[Fact]
public async Task GetConcernsCaseByOwnerId()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,25 @@ public DeleteConcernsCase(ConcernsDbContext concernsDbContext)
_context = concernsDbContext;
}


public UseCaseResult Execute(int id)
{

bool HasConcernsRecord = _context.ConcernsRecord.Where(f => f.CaseId == id).Any();
bool HasDecisions = _context.Decisions.Where(f => f.ConcernsCaseId == id).Any();
bool HasNoticeToImprove = _context.NoticesToImprove.Where(f => f.CaseUrn == id).Any();
bool HasNTIUnderconsideration = _context.NTIUnderConsiderations.Where(f => f.CaseUrn == id).Any();
bool HasNTIWarningLetters = _context.NTIWarningLetters.Where(f => f.CaseUrn == id).Any();
bool HasFinancialPlans = _context.FinancialPlanCases.Where(f => f.CaseUrn == id).Any();
bool HasSRMAs = _context.SRMACases.Where(f => f.CaseUrn == id).Any();
bool HasTFF = _context.TrustFinancialForecasts.Where(f => f.CaseUrn == id).Any();

bool HasNoRelatedCaseActions = new[] { HasDecisions, HasNoticeToImprove, HasNTIUnderconsideration, HasNTIWarningLetters, HasFinancialPlans, HasSRMAs, HasTFF }.All(x => x == false);


if (HasConcernsRecord && !HasNoRelatedCaseActions)
return UseCaseResult.Failure(new UseCaseResultError($"Cannot deleted Case. Case has related concern(s) and case actions"));

if (HasConcernsRecord)
return UseCaseResult.Failure(new UseCaseResultError($"Cannot deleted Case. Case has related concern(s)"));

if (!HasNoRelatedCaseActions)
return UseCaseResult.Failure(new UseCaseResultError($"Cannot deleted Case. Case has related case actions"));
var cc = _context.ConcernsCase.SingleOrDefault(f => f.Id == id);
cc.DeletedAt = DateTime.Now;
bool hasRelatedRecords = _context.ConcernsRecord.Any(f => f.CaseId == id) ||
_context.Decisions.Any(f => f.ConcernsCaseId == id) ||
_context.NoticesToImprove.Any(f => f.CaseUrn == id) ||
_context.NTIUnderConsiderations.Any(f => f.CaseUrn == id) ||
_context.NTIWarningLetters.Any(f => f.CaseUrn == id) ||
_context.FinancialPlanCases.Any(f => f.CaseUrn == id) ||
_context.SRMACases.Any(f => f.CaseUrn == id) ||
_context.TrustFinancialForecasts.Any(f => f.CaseUrn == id);

if (hasRelatedRecords)
return UseCaseResult.Failure(new UseCaseResultError($"Cannot deleted Case. Case has related concern(s) or case actions"));

var concernsCase = _context.ConcernsCase.SingleOrDefault(f => f.Id == id);
if (concernsCase == null)
return UseCaseResult.Failure(new UseCaseResultError("Case not found."));

concernsCase.DeletedAt = DateTime.Now;
_context.SaveChanges();

return UseCaseResult.Success();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Ardalis.GuardClauses;
using ConcernsCaseWork.API.Contracts.Permissions;
using ConcernsCaseWork.Data.Models;
using ConcernsCaseWork.UserContext;

namespace ConcernsCaseWork.API.Features.Permissions;

/// <summary>
/// A strategy for inspecting a case and user and determining if the user is permitted to delete the case & entities.
/// </summary>
public class IsCaseDeletableStrategy : ICaseActionPermissionStrategy
{
/// <summary>
/// Inspects the case and user info passed and determines if the user should be permitted to delete the case & entities.
/// </summary>
/// <param name="concernsCase">The case to be considered. If null then none permission will be returned</param>
/// <param name="userInfo">The user info to be considered. If null then an exception will be thrown</param>
/// <returns></returns>
public CasePermission GetAllowedActionPermission(ConcernsCase concernsCase, UserInfo userInfo)
{
// Deletable if user is delete case admin group.
// Otherwise not deletable

if (concernsCase == null)
return CasePermission.None;

Guard.Against.Null(userInfo);

if (userInfo.IsInCaseDeleteGroup())
return CasePermission.EditAndDelete;

return CasePermission.None;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ public static IServiceCollection AddApiDependencies(this IServiceCollection serv
services.AddScoped<ICaseActionPermissionStrategyRoot, CaseActionPermissionStrategyRoot>();
services.AddScoped<ICaseActionPermissionStrategy, IsCaseViewableStrategy>();
services.AddScoped<ICaseActionPermissionStrategy, IsCaseEditableStrategy>();
services.AddScoped<ICaseActionPermissionStrategy, IsCaseDeletableStrategy>();

services.AddScoped<IGetCasePermissionsUseCase, GetCasePermissionsUseCase>();

services.AddScoped<ICorrelationContext, CorrelationContext>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
{ "caseworker", new OpenApiExample(){ Value = new OpenApiString("concerns-casework.caseworker") } },
{ "team-leader", new OpenApiExample(){ Value = new OpenApiString("concerns-casework.teamleader") } },
{ "admin", new OpenApiExample(){ Value = new OpenApiString("concerns-casework.admin") } }
{ "admin", new OpenApiExample(){ Value = new OpenApiString("concerns-casework.admin") } },
{ "case-delete-group", new OpenApiExample(){ Value = new OpenApiString("concerns-casework.case-delete-group") } }
},
Required = true,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import actionSummaryTable from "cypress/pages/caseActions/summary/actionSummaryT
import { toDisplayDate } from "cypress/support/formatDate";
import { DateIncompleteError, DateInvalidError, NotesError } from "cypress/constants/validationErrorConstants";
import validationComponent from "cypress/pages/validationComponent";
import { DeleteDecisionPage } from "cypress/pages/caseActions/decision/deleteDecisionPage";

describe("User can add decisions to an existing case", () => {
const viewDecisionPage = new ViewDecisionPage();
const editDecisionPage = new EditDecisionPage();
const closeDecisionPage = new CloseDecisionPage();
const deleteDecisionPage = new DeleteDecisionPage();
const decisionOutcomePage = new DecisionOutcomePage();

let now: Date;
Expand Down Expand Up @@ -502,4 +504,54 @@ describe("User can add decisions to an existing case", () => {
.hasBusinessArea("Regions Group")
.hasBusinessArea("Funding");
});

it("Creating and deleting a decision", function () {
const repayableFinancialSupportOption = "RepayableFinancialSupport";
const shortTermCashAdvanceOption = "ShortTermCashAdvance";

Logger.log("Validating Decision");

Logger.log("Creating Decision");
editDecisionPage
.withHasCrmCase("yes")
.withCrmEnquiry("444")
.withRetrospectiveRequest("no")
.withSubmissionRequired("yes")
.withSubmissionLink("www.gov.uk")
.withDateESFADay("21")
.withDateESFAMonth("04")
.withDateESFAYear("2022")
.withTypeOfDecision("NoticeToImprove")
.withTypeOfDecision("Section128")
.withTypeOfDecision(repayableFinancialSupportOption)
.withDrawdownFacilityAgreed(repayableFinancialSupportOption, "Yes")
.withFrameworkCategory(repayableFinancialSupportOption, "BuildingFinancialCapability")
.withTypeOfDecision(shortTermCashAdvanceOption)
.withDrawdownFacilityAgreed(shortTermCashAdvanceOption, "PaymentUnderExistingArrangement")
.withTotalAmountRequested("£140,000")
.withSupportingNotes("These are some supporting notes!")
.save();

Logger.log("Selecting Decision from open actions");
actionSummaryTable
.getOpenAction("Decision: Multiple Decision Types")
.then(row =>
{
row.hasName("Decision: Multiple Decision Types")
row.hasStatus("In progress")
row.hasCreatedDate(toDisplayDate(now));
row.select();
});

Logger.log("Deleting Decision");
viewDecisionPage
.deleteDecision();

deleteDecisionPage
.delete();

Logger.log("Confirm Decision no longer exist");
actionSummaryTable
.assertRowDoesNotExist("Decision: Multiple Decision Types", "open");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import CaseManagementPage from "../../../pages/caseMangementPage";
import actionSummaryTable from "cypress/pages/caseActions/summary/actionSummaryTable";
import { toDisplayDate } from "cypress/support/formatDate";
import { DateIncompleteError, DateInvalidError, NotesError } from "cypress/constants/validationErrorConstants";
import { DeleteFinancialPlanPage } from "cypress/pages/caseActions/financialPlan/DeleteFinancialPlanPage";

describe("User can add Financial Plan case action to an existing case", () => {
let viewFinancialPlanPage = new ViewFinancialPlanPage();
let editFinancialPlanPage = new EditFinancialPlanPage();
let closeFinancialPlanPage = new CloseFinancialPlanPage();
let deleteFinancialPlanPage = new DeleteFinancialPlanPage();
let now: Date;

beforeEach(() => {
Expand Down Expand Up @@ -230,6 +232,48 @@ describe("User can add Financial Plan case action to an existing case", () => {
cy.excuteAccessibilityTests();
});

it("Should add and delete a financial plan", () =>
{
Logger.log("Configuring a valid financial plan");

editFinancialPlanPage
.withPlanRequestedDay("06")
.withPlanRequestedMonth("07")
.withPlanRequestedYear("2022")
.withNotes("Notes!")
.save();

Logger.log("Selecting Financial Plan from open actions");
actionSummaryTable
.getOpenAction("Financial Plan")
.then(row =>
{
row.hasName("Financial Plan")
row.hasStatus("In progress")
row.hasCreatedDate(toDisplayDate(now))
row.select();
});

Logger.log("Checking Financial Plan values");

viewFinancialPlanPage
.hasDateOpened(toDisplayDate(now))
.hasPlanRequestedDate("06 July 2022")
.hasNotes("Notes!");


Logger.log("Delete Financial Plan");
viewFinancialPlanPage
.delete();

deleteFinancialPlanPage
.delete();

Logger.log("Confirm Financial Plan no longer exist");
actionSummaryTable
.assertRowDoesNotExist("Financial Plan", "open");
});

function checkFormValidation()
{
Logger.log("Incomplete plan requested date");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import { CloseNtiUnderConsiderationPage } from "../../../pages/caseActions/ntiUn
import actionSummaryTable from "cypress/pages/caseActions/summary/actionSummaryTable";
import { toDisplayDate } from "cypress/support/formatDate";
import {NotesError} from "../../../constants/validationErrorConstants";
import { DeleteNtiUnderConsiderationPage } from "cypress/pages/caseActions/ntiUnderConsideration/deleteNtiUnderConsiderationPage";

describe("Testing the NTI under consideration", () =>
{
const editNtiUnderConsiderationPage = new EditNtiUnderConsiderationPage();
const viewNtiUnderConsiderationPage = new ViewNtiUnderConsiderationPage();
const closeNtiUnderConsiderationPage = new CloseNtiUnderConsiderationPage();
const deleteNtiUnderConsiderationPage = new DeleteNtiUnderConsiderationPage();
let now: Date;

beforeEach(() => {
Expand Down Expand Up @@ -194,6 +196,34 @@ describe("Testing the NTI under consideration", () =>
});
});

describe("When deleting an NTI under consideration", () =>
{
it("Should be able to delete the NTI under consideration", () =>
{
editNtiUnderConsiderationPage
.withReason("Cash flow problems")
.withReason("Safeguarding")
.withNotes("These are my notes")
.save();

Logger.log("Close NTI on the view page");
actionSummaryTable
.getOpenAction("NTI Under Consideration")
.then(row =>
{
row.select();
});

Logger.log("Delete the NTI UC");
viewNtiUnderConsiderationPage.delete();
deleteNtiUnderConsiderationPage.delete();

Logger.log("Confirm NTI UC no longer exist");
actionSummaryTable
.assertRowDoesNotExist("NTI Under Consideration", "open");
});
});

function addNtiUnderConsiderationToCase()
{
Logger.log("Adding Notice To Improve");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import { CloseNtiWarningLetterPage } from "../../../pages/caseActions/ntiWarning
import actionSummaryTable from "cypress/pages/caseActions/summary/actionSummaryTable";
import { toDisplayDate } from "cypress/support/formatDate";
import { DateIncompleteError, DateInvalidError, NotesError } from "cypress/constants/validationErrorConstants";
import { DeleteNtiWarningLetterPage } from "cypress/pages/caseActions/ntiWarningLetter/deleteNtiWarningLetterPage";

describe("Testing the NTI warning letter action", () =>
{
const editNtiWarningLetterPage = new EditNtiWarningLetterPage();
const viewNtiWarningLetterPage = new ViewNtiWarningLetterPage();
const closeNtiWarningLetterPage = new CloseNtiWarningLetterPage();
const deleteNtiWarningLetterPage = new DeleteNtiWarningLetterPage();
let now;

beforeEach(() => {
Expand Down Expand Up @@ -229,6 +231,28 @@ describe("Testing the NTI warning letter action", () =>
cy.excuteAccessibilityTests();
});

it("Should be able to delete an NTI warning letter", () =>
{
createConfiguredNtiWarningLetter();

Logger.log("Closing the NTI warning letter");
actionSummaryTable
.getOpenAction("NTI Warning Letter")
.then(row =>
{
row.select();
});

Logger.log("Delete the NTI WL");
viewNtiWarningLetterPage.delete();
deleteNtiWarningLetterPage.delete();

Logger.log("Confirm NTI WL no longer exist");
actionSummaryTable
.assertRowDoesNotExist("NTI Warning Letter", "open");

});

function createConfiguredNtiWarningLetter()
{
Logger.log("Filling out the form");
Expand Down
Loading

0 comments on commit bdce560

Please sign in to comment.