Skip to content

Commit

Permalink
drop date approval and date validation when going to draft status
Browse files Browse the repository at this point in the history
  • Loading branch information
JeromeBu committed Dec 17, 2024
1 parent 4308bbc commit 94e6fc6
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ describe("PgConventionRepository", () => {
);
});

it("update convention with dateApproval and drops it when undefined", async () => {
it("Update convention with dateApproval and drops it when undefined", async () => {
const conventionId: ConventionId = "aaaaac99-9c0b-1aaa-aa6d-6bb9bd38aaaa";
const convention = conventionStylisteBuilder
.withId(conventionId)
Expand All @@ -806,6 +806,19 @@ describe("PgConventionRepository", () => {
expect(await conventionRepository.getById(conventionId)).toEqual(
updatedConvention,
);

const conventionBackToDraft: ConventionDto = {
...updatedConvention,
status: "DRAFT",
dateApproval: undefined,
};

await conventionRepository.update(conventionBackToDraft);

expectToEqual(
await conventionRepository.getById(conventionId),
conventionBackToDraft,
);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ export class PgConventionRepository implements ConventionRepository {
date_start: convention.dateStart,
date_end: convention.dateEnd,
date_validation: convention.dateValidation,
date_approval: convention.dateApproval,
date_approval: convention.dateApproval ?? null,
siret: convention.siret,
business_name: convention.businessName,
schedule: sql`${JSON.stringify(convention.schedule)}`,
Expand Down
13 changes: 10 additions & 3 deletions back/src/domains/convention/use-cases/UpdateConventionStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ConventionReadDto,
ConventionRelatedJwtPayload,
ConventionStatus,
DateString,
Email,
InclusionConnectedUser,
Role,
Expand Down Expand Up @@ -142,15 +143,21 @@ export class UpdateConventionStatus extends TransactionalUseCase<
params.status === "ACCEPTED_BY_VALIDATOR" &&
(params.lastname || params.firstname);

const getDateApproval = (): DateString | undefined => {
if (reviewedConventionStatuses.includes(params.status))
return conventionUpdatedAt;
if (validatedConventionStatuses.includes(params.status))
return conventionRead.dateApproval;
return undefined;
};

const updatedConvention: ConventionDto = {
...conventionRead,
status: params.status,
dateValidation: validatedConventionStatuses.includes(params.status)
? conventionUpdatedAt
: undefined,
dateApproval: reviewedConventionStatuses.includes(params.status)
? conventionUpdatedAt
: undefined,
dateApproval: getDateApproval(),
statusJustification,
...(hasCounsellor
? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import {
AgencyDtoBuilder,
ConventionDtoBuilder,
ConventionId,
InclusionConnectedUserBuilder,
createConventionMagicLinkPayload,
errors,
expectObjectInArrayToMatch,
expectObjectsToMatch,
expectPromiseToFailWithError,
validSignatoryRoles,
Expand All @@ -12,7 +14,10 @@ import { toAgencyWithRights } from "../../../utils/agency";
import { makeCreateNewEvent } from "../../core/events/ports/EventBus";
import { CustomTimeGateway } from "../../core/time-gateway/adapters/CustomTimeGateway";
import { InMemoryUowPerformer } from "../../core/unit-of-work/adapters/InMemoryUowPerformer";
import { createInMemoryUow } from "../../core/unit-of-work/adapters/createInMemoryUow";
import {
InMemoryUnitOfWork,
createInMemoryUow,
} from "../../core/unit-of-work/adapters/createInMemoryUow";
import { TestUuidGenerator } from "../../core/uuid-generator/adapters/UuidGeneratorImplementations";
import { UpdateConventionStatus } from "./UpdateConventionStatus";
import {
Expand Down Expand Up @@ -98,6 +103,7 @@ describe("UpdateConventionStatus", () => {
"ACCEPTED_BY_COUNSELLOR",
],
});

rejectStatusTransitionTests({
updateStatusParams: {
status: "DRAFT",
Expand Down Expand Up @@ -129,88 +135,128 @@ describe("UpdateConventionStatus", () => {
],
});

it("Accept from role establishment-representative when convention is requested to be modified for the second time", async () => {
const uow = createInMemoryUow();
const timeGateway = new CustomTimeGateway();
const createNewEvent = makeCreateNewEvent({
timeGateway,
uuidGenerator: new TestUuidGenerator(),
describe("standalone tests", () => {
let uow: InMemoryUnitOfWork;
let updateConventionStatusUseCase: UpdateConventionStatus;

beforeEach(() => {
({ uow, updateConventionStatusUseCase } =
prepareUseCaseForStandAloneTests());
});

const agency = toAgencyWithRights(new AgencyDtoBuilder().build(), {});
it("Accept from role establishment-representative when convention is requested to be modified for the second time", async () => {
const agency = toAgencyWithRights(new AgencyDtoBuilder().build(), {});

const initialConvention = new ConventionDtoBuilder()
.withId(conventionWithAgencyOneStepValidationId)
.withStatus("READY_TO_SIGN")
.withEstablishmentRepresentativeEmail("[email protected]")
.withAgencyId(agency.id)
.withInternshipKind("mini-stage-cci")
.withBeneficiaryRepresentative({
role: "beneficiary-representative",
email: "[email protected]",
firstName: "Bruce",
lastName: "Wayne",
phone: "#33112233445",
signedAt: undefined,
})
.build();

const establishmentRepresentativeJwtPayload =
createConventionMagicLinkPayload({
id: conventionWithAgencyOneStepValidationId,
role: "establishment-representative",
email: "[email protected]",
now: new Date(),
});

await uow.agencyRepository.insert(agency);
await uow.conventionRepository.save(initialConvention);

await updateConventionStatusUseCase.execute(
{
status: "DRAFT",
statusJustification: "first modification",
modifierRole: "establishment-representative",
conventionId: conventionWithAgencyOneStepValidationId,
},
establishmentRepresentativeJwtPayload,
);

const updatedConventionAfterFirstModificationRequest =
await uow.conventionRepository.getById(initialConvention.id);

const signedConvention = new ConventionDtoBuilder(
updatedConventionAfterFirstModificationRequest,
)
.withBeneficiarySignedAt(new Date())
.withBeneficiaryRepresentativeSignedAt(new Date())
.withStatus("PARTIALLY_SIGNED")
.build();
await uow.conventionRepository.update(signedConvention);

await updateConventionStatusUseCase.execute(
{
status: "DRAFT",
statusJustification: "second modification",
modifierRole: "establishment-representative",
conventionId: conventionWithAgencyOneStepValidationId,
},
establishmentRepresentativeJwtPayload,
);

const initialConvention = new ConventionDtoBuilder()
.withId(conventionWithAgencyOneStepValidationId)
.withStatus("READY_TO_SIGN")
.withEstablishmentRepresentativeEmail("[email protected]")
.withAgencyId(agency.id)
.withInternshipKind("mini-stage-cci")
.withBeneficiaryRepresentative({
role: "beneficiary-representative",
email: "[email protected]",
firstName: "Bruce",
lastName: "Wayne",
phone: "#33112233445",
signedAt: undefined,
})
.build();
const updatedConventionAfterSecondModificationRequest =
await uow.conventionRepository.getById(initialConvention.id);

expect(
updatedConventionAfterSecondModificationRequest.signatories
.beneficiary.signedAt,
).toBeUndefined();
});

const establishmentRepresentativeJwtPayload =
createConventionMagicLinkPayload({
id: conventionWithAgencyOneStepValidationId,
role: "establishment-representative",
email: "[email protected]",
it("removes date approval when going to status DRAFT", async () => {
const user = new InclusionConnectedUserBuilder()
.withEmail("[email protected]")
.buildUser();
const agency = toAgencyWithRights(new AgencyDtoBuilder().build(), {
[user.id]: { roles: ["validator"], isNotifiedByEmail: true },
});
const dateApproval = new Date("2024-04-29").toISOString();
const convention = new ConventionDtoBuilder()
.withStatus("IN_REVIEW")
.withAgencyId(agency.id)
.withDateApproval(dateApproval)
.build();

uow.userRepository.users = [user];
await uow.agencyRepository.insert(agency);
uow.conventionRepository.setConventions([convention]);

const validatorJwtPayload = createConventionMagicLinkPayload({
id: convention.id,
role: "validator",
email: user.email,
now: new Date(),
});

await uow.agencyRepository.insert(agency);
await uow.conventionRepository.save(initialConvention);

const updateConventionStatusUseCase = new UpdateConventionStatus(
new InMemoryUowPerformer(uow),
createNewEvent,
timeGateway,
);

await updateConventionStatusUseCase.execute(
{
status: "DRAFT",
statusJustification: "first modification",
modifierRole: "establishment-representative",
conventionId: conventionWithAgencyOneStepValidationId,
},
establishmentRepresentativeJwtPayload,
);

const updatedConventionAfterFirstModificationRequest =
await uow.conventionRepository.getById(initialConvention.id);

const signedConvention = new ConventionDtoBuilder(
updatedConventionAfterFirstModificationRequest,
)
.withBeneficiarySignedAt(new Date())
.withBeneficiaryRepresentativeSignedAt(new Date())
.withStatus("PARTIALLY_SIGNED")
.build();
await uow.conventionRepository.update(signedConvention);

await updateConventionStatusUseCase.execute(
{
status: "DRAFT",
statusJustification: "second modification",
modifierRole: "establishment-representative",
conventionId: conventionWithAgencyOneStepValidationId,
},
establishmentRepresentativeJwtPayload,
);

const updatedConventionAfterSecondModificationRequest =
await uow.conventionRepository.getById(initialConvention.id);
await updateConventionStatusUseCase.execute(
{
status: "DRAFT",
statusJustification: "Ca va pas",
conventionId: convention.id,
modifierRole: "validator",
},
validatorJwtPayload,
);

expect(
updatedConventionAfterSecondModificationRequest.signatories.beneficiary
.signedAt,
).toBeUndefined();
expectObjectInArrayToMatch(uow.conventionRepository.conventions, [
{
status: "DRAFT",
dateApproval: undefined,
},
]);
});
});

it("ConventionRequiresModification event only has the role of the user that requested the change", async () => {
Expand Down Expand Up @@ -559,6 +605,51 @@ describe("UpdateConventionStatus", () => {
},
nextDate: validationDate,
});

it("keeps date approval when going to status ACCEPTED_BY_VALIDATOR", async () => {
const { uow, updateConventionStatusUseCase } =
prepareUseCaseForStandAloneTests();
const user = new InclusionConnectedUserBuilder()
.withEmail("[email protected]")
.buildUser();
const agency = toAgencyWithRights(new AgencyDtoBuilder().build(), {
[user.id]: { roles: ["validator"], isNotifiedByEmail: true },
});
const dateApproval = new Date("2024-04-29").toISOString();
const convention = new ConventionDtoBuilder()
.withStatus("ACCEPTED_BY_COUNSELLOR")
.withAgencyId(agency.id)
.withDateApproval(dateApproval)
.build();

uow.userRepository.users = [user];
await uow.agencyRepository.insert(agency);
uow.conventionRepository.setConventions([convention]);

const validatorJwtPayload = createConventionMagicLinkPayload({
id: convention.id,
role: "validator",
email: user.email,
now: new Date(),
});

await updateConventionStatusUseCase.execute(
{
status: "ACCEPTED_BY_VALIDATOR",
conventionId: convention.id,
firstname: "Joe",
lastname: "Validator",
},
validatorJwtPayload,
);

expectObjectInArrayToMatch(uow.conventionRepository.conventions, [
{
status: "ACCEPTED_BY_VALIDATOR",
dateApproval,
},
]);
});
});
});

Expand Down Expand Up @@ -743,3 +834,21 @@ describe("UpdateConventionStatus", () => {
);
});
});

const prepareUseCaseForStandAloneTests = () => {
const uow = createInMemoryUow();
const timeGateway = new CustomTimeGateway();
const createNewEvent = makeCreateNewEvent({
timeGateway,
uuidGenerator: new TestUuidGenerator(),
});
const updateConventionStatusUseCase = new UpdateConventionStatus(
new InMemoryUowPerformer(uow),
createNewEvent,
timeGateway,
);
return {
uow,
updateConventionStatusUseCase,
};
};

0 comments on commit 94e6fc6

Please sign in to comment.