Skip to content

Commit

Permalink
feat(4276): add cancel operations for private/public clouds
Browse files Browse the repository at this point in the history
  • Loading branch information
Chinedu Olebu committed Jan 11, 2025
1 parent be8a4e8 commit 46b3baa
Show file tree
Hide file tree
Showing 37 changed files with 401 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ localmac:

.PHONY: dev
dev:
@DATABASE_URL=$$(grep -m 1 '^DATABASE_URL=' app/.env.local | cut -d '=' -f 2-) \
@DATABASE_URL=$$(grep -m 1 '^DATABASE_URL=' app/.env.apple.local | cut -d '=' -f 2-) \
npm run prisma-push --prefix app && \
npm run dev --prefix app

Expand Down
4 changes: 2 additions & 2 deletions app/app/api/billing/[idOrAccountCoding]/download/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ export const GET = apiHandler(async ({ pathParams, queryParams, session }) => {

const canDownloadMou =
session.permissions.downloadBillingMou ||
product.members.some(
product?.members.some(
(member) =>
member.userId === session.user.id &&
arraysIntersect(member.roles, [PublicCloudProductMemberRole.BILLING_VIEWER]),
);

if (!canDownloadMou) {
if (!canDownloadMou || !product) {
return UnauthorizedResponse();
}

Expand Down
38 changes: 37 additions & 1 deletion app/app/api/private-cloud/requests/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { DecisionStatus, EventType } from '@prisma/client';
import { z } from 'zod';
import { GlobalRole } from '@/constants';
import createApiHandler from '@/core/api-handler';
import { OkResponse, UnauthorizedResponse } from '@/core/responses';
import { models } from '@/services/db';
import { createEvent, models } from '@/services/db';

const pathParamSchema = z.object({
id: z.string(),
Expand All @@ -12,6 +13,7 @@ const apiHandler = createApiHandler({
roles: [GlobalRole.User],
validations: { pathParams: pathParamSchema },
});

export const GET = apiHandler(async ({ pathParams, queryParams, session }) => {
const { id } = pathParams;

Expand All @@ -23,3 +25,37 @@ export const GET = apiHandler(async ({ pathParams, queryParams, session }) => {

return OkResponse(request);
});

export const PUT = apiHandler(async ({ pathParams, session }) => {
const { id } = pathParams;

const { data: request } = await models.privateCloudRequest.get({ where: { id } }, session);

if (!request?._permissions.cancel) {
return UnauthorizedResponse();
}

const updatedRequest = await models.privateCloudRequest.update(
{
where: {
id,
decisionStatus: DecisionStatus.PENDING,
active: true,
},
data: {
decisionStatus: DecisionStatus.CANCELLED,
},
select: {
decisionStatus: true,
createdByEmail: true,
},
},
session,
);

if (updatedRequest) {
await createEvent(EventType.CANCEL_PRIVATE_CLOUD_REQUEST, session.user.id, { requestId: id });
}

return OkResponse(updatedRequest);
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const POST = apiHandler(async ({ pathParams, body, session }) => {
include: publicCloudRequestDetailInclude,
});

if (request) {
if (request && request.decisionData.billingId) {
const billing = await prisma.billing.update({
where: {
id: request?.decisionData.billingId,
Expand Down
2 changes: 1 addition & 1 deletion app/app/api/public-cloud/products/_operations/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export default async function createOp({ session, body }: { session: Session; bo
const proms = [];

// Assign a task to the expense authority for new billing
if (newRequest.decisionData.expenseAuthorityId && !newRequest.decisionData.billing.signed) {
if (newRequest.decisionData.expenseAuthorityId && !newRequest.decisionData.billing?.signed) {
const taskProm = tasks.create(TaskType.SIGN_PUBLIC_CLOUD_MOU, { request: newRequest });
proms.push(taskProm);
} else {
Expand Down
22 changes: 20 additions & 2 deletions app/app/api/public-cloud/products/_operations/update.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DecisionStatus, Prisma, RequestType, EventType, TaskType } from '@prisma/client';
import { Session } from 'next-auth';
import { TypeOf } from 'zod';
import prisma from '@/core/prisma';
import { OkResponse, UnauthorizedResponse } from '@/core/responses';
import { comparePublicProductData } from '@/helpers/product-change';
import { sendEditRequestEmails } from '@/services/ches/public-cloud';
Expand Down Expand Up @@ -40,13 +41,28 @@ export default async function updateOp({
body.expenseAuthority?.email,
]);

const billingInfo = product.billingId
? await prisma.billing.findFirst({
where: {
id: product.billingId,
},
})
: null;

const decisionData = {
...rest,
licencePlate: product.licencePlate,
status: product.status,
provider: product.provider,
createdAt: product.createdAt,
billing: { connect: { id: product.billingId } },
billing: product.billingId
? {
connect: {
id: product.billingId,
code: billingInfo?.code,
},
}
: undefined, // Handle the case where `billingId` is null
projectOwner: { connect: { email: body.projectOwner.email } },
primaryTechnicalLead: { connect: { email: body.primaryTechnicalLead.email } },
secondaryTechnicalLead: body.secondaryTechnicalLead
Expand All @@ -72,7 +88,9 @@ export default async function updateOp({
requestComment,
changes: otherChangeMeta,
originalData: { connect: { id: previousRequest?.decisionDataId } },
decisionData: { create: decisionData },
decisionData: {
create: decisionData,
},
requestData: { create: decisionData },
project: { connect: { licencePlate: product.licencePlate } },
},
Expand Down
91 changes: 90 additions & 1 deletion app/app/api/public-cloud/requests/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { DecisionStatus, EventType, PublicCloudRequest } from '@prisma/client';
import { z } from 'zod';
import { GlobalRole } from '@/constants';
import createApiHandler from '@/core/api-handler';
import prisma from '@/core/prisma';
import { OkResponse, UnauthorizedResponse } from '@/core/responses';
import { models } from '@/services/db';
import { createEvent, models } from '@/services/db';

const pathParamSchema = z.object({
id: z.string(),
Expand All @@ -23,3 +25,90 @@ export const GET = apiHandler(async ({ pathParams, queryParams, session }) => {

return OkResponse(request);
});

export const PUT = apiHandler(async ({ pathParams, session }) => {
const { id } = pathParams;

const { data: request } = await models.publicCloudRequest.get({ where: { id } }, session);

if (!request?._permissions.cancel) {
return UnauthorizedResponse();
}

const { data: updatedRequest } = await models.publicCloudRequest.update(
{
where: {
id,
decisionStatus: DecisionStatus.PENDING,
active: true,
},
data: {
decisionStatus: DecisionStatus.CANCELLED,
},
select: {
decisionStatus: true,
createdByEmail: true,
licencePlate: true,
decisionData: true,
decisionDataId: true,
requestDataId: true,
createdBy: {
select: {
id: true,
},
},
},
},
session,
);

const { decisionDataId, requestDataId, licencePlate } = updatedRequest as unknown as PublicCloudRequest;

const billingData = await prisma.billing.findFirst({
where: {
licencePlate,
},
select: {
expenseAuthorityId: true,
},
});

await prisma.publicCloudRequestedProject.updateMany({
where: {
expenseAuthorityId: billingData?.expenseAuthorityId,
},
data: {
expenseAuthorityId: null,
billingId: null,
},
});

await prisma.billing.deleteMany({
where: {
licencePlate,
signed: false,
},
});

await prisma.task.deleteMany({
where: {
data: {
equals: {
licencePlate,
},
},
},
});

await prisma.publicCloudRequest.update({
where: { id },
data: {
decisionDataId,
requestDataId,
},
});

await createEvent(EventType.CANCEL_PUBLIC_CLOUD_REQUEST, session.user.id, { requestId: id });

return OkResponse(true);
});
10 changes: 9 additions & 1 deletion app/app/private-cloud/requests/(request)/[id]/request/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { PrivateCloudProject } from '@prisma/client';
import { DecisionStatus, PrivateCloudProject } from '@prisma/client';
import {
IconInfoCircle,
IconUsersGroup,
Expand All @@ -9,9 +9,11 @@ import {
IconMessage,
IconWebhook,
} from '@tabler/icons-react';
import { useSession } from 'next-auth/react';
import { useEffect, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { z } from 'zod';
import CancelRequest from '@/components/buttons/CancelButton';
import PreviousButton from '@/components/buttons/Previous';
import ProjectDescription from '@/components/form/ProjectDescriptionPrivate';
import TeamContacts from '@/components/form/TeamContacts';
Expand Down Expand Up @@ -133,6 +135,9 @@ export default privateCloudRequestRequest(({}) => {
});
}

const { data: session } = useSession();
const canCancel = session?.user.email === snap.currentRequest.createdByEmail;

return (
<div>
<FormProvider {...methods}>
Expand All @@ -141,6 +146,9 @@ export default privateCloudRequestRequest(({}) => {

<div className="mt-5 flex items-center justify-start gap-x-2">
<PreviousButton />
{snap.currentRequest.decisionStatus === DecisionStatus.PENDING && canCancel && (
<CancelRequest id={snap.currentRequest.id} context={'PRIVATE'} />
)}
</div>
</form>
</FormProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default publicCloudProductEdit(({}) => {
defaultValues: {
...snap.currentProduct,
isAgMinistryChecked: true,
accountCoding: snap.currentProduct?.billing.accountCoding,
accountCoding: snap.currentProduct?.billing?.accountCoding,
},
});

Expand Down Expand Up @@ -131,7 +131,7 @@ export default publicCloudProductEdit(({}) => {
label: 'Billing (Account coding)',
description: '',
Component: AccountCoding,
componentArgs: { accountCodingInitial: snap.currentProduct?.billing.accountCoding, disabled: true },
componentArgs: { accountCodingInitial: snap.currentProduct?.billing?.accountCoding, disabled: true },
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export default publicCloudRequestOriginal(({ router }) => {
description: '',
Component: AccountCoding,
componentArgs: {
accountCodingInitial: snap.currentRequest.originalData?.billing.accountCoding,
accountCodingInitial: snap.currentRequest.originalData?.billing?.accountCoding,
disabled: true,
},
},
Expand Down
2 changes: 1 addition & 1 deletion app/app/public-cloud/requests/(request)/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export default publicCloudRequest(({ getPathParams }) => {
label: 'Billing (account coding)',
description: '',
Component: AccountCoding,
componentArgs: { accountCodingInitial: request.decisionData.billing.accountCoding, disabled: true },
componentArgs: { accountCodingInitial: request.decisionData.billing?.accountCoding, disabled: true },
},
];

Expand Down
Loading

0 comments on commit 46b3baa

Please sign in to comment.