Skip to content

Commit

Permalink
Merge branch '#3074-GetUnreadAnnouncements' into #3075-RemoveAnnounce…
Browse files Browse the repository at this point in the history
…ment
  • Loading branch information
caiodasilva2005 committed Dec 20, 2024
2 parents 6446202 + 0dfedd2 commit 763183f
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export type AnnouncementQueryArgs = ReturnType<typeof getAnnouncementQueryArgs>;
export const getAnnouncementQueryArgs = (organizationId: string) =>
Prisma.validator<Prisma.AnnouncementDefaultArgs>()({
include: {
usersReceived: getUserQueryArgs(organizationId),
userCreated: getUserQueryArgs(organizationId)
usersReceived: getUserQueryArgs(organizationId)
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ CREATE TABLE "Announcement" (
"announcementId" TEXT NOT NULL,
"text" TEXT NOT NULL,
"dateCreated" TIMESTAMP(3) NOT NULL,
"userCreatedId" TEXT NOT NULL,
"dateDeleted" TIMESTAMP(3),
"senderName" TEXT NOT NULL,
"slackEventId" TEXT NOT NULL,
"slackChannelName" TEXT NOT NULL,

Expand Down Expand Up @@ -38,6 +39,9 @@ CREATE TABLE "_userNotifications" (
"B" TEXT NOT NULL
);

-- CreateIndex
CREATE UNIQUE INDEX "Announcement_slackEventId_key" ON "Announcement"("slackEventId");

-- CreateIndex
CREATE UNIQUE INDEX "_receivedAnnouncements_AB_unique" ON "_receivedAnnouncements"("A", "B");

Expand All @@ -53,9 +57,6 @@ CREATE INDEX "_userNotifications_B_index" ON "_userNotifications"("B");
-- AddForeignKey
ALTER TABLE "Project" ADD CONSTRAINT "Project_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Announcement" ADD CONSTRAINT "Announcement_userCreatedId_fkey" FOREIGN KEY ("userCreatedId") REFERENCES "User"("userId") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "_receivedAnnouncements" ADD CONSTRAINT "_receivedAnnouncements_A_fkey" FOREIGN KEY ("A") REFERENCES "Announcement"("announcementId") ON DELETE CASCADE ON UPDATE CASCADE;

Expand Down
11 changes: 5 additions & 6 deletions src/backend/src/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,6 @@ model User {
createdMilestones Milestone[] @relation(name: "milestoneCreator")
deletedMilestones Milestone[] @relation(name: "milestoneDeleter")
unreadAnnouncements Announcement[] @relation(name: "receivedAnnouncements")
createdAnnouncements Announcement[] @relation(name: "createdAnnouncements")
unreadNotifications Notification[] @relation(name: "userNotifications")
}

Expand Down Expand Up @@ -932,13 +931,13 @@ model Milestone {
}

model Announcement {
announcementId String @id @default(uuid())
announcementId String @id @default(uuid())
text String
usersReceived User[] @relation("receivedAnnouncements")
usersReceived User[] @relation("receivedAnnouncements")
dateCreated DateTime
userCreatedId String
userCreated User @relation("createdAnnouncements", fields: [userCreatedId], references: [userId])
slackEventId String
dateDeleted DateTime?
senderName String
slackEventId String @unique
slackChannelName String
}

Expand Down
12 changes: 11 additions & 1 deletion src/backend/src/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { writeFileSync } from 'fs';
import WorkPackageTemplatesService from '../services/work-package-template.services';
import RecruitmentServices from '../services/recruitment.services';
import OrganizationsService from '../services/organizations.services';
import NotificationsService from '../services/notifications.services';
import AnnouncementService from '../services/announcement.service';

const prisma = new PrismaClient();

Expand Down Expand Up @@ -1894,6 +1894,16 @@ const performSeed: () => Promise<void> = async () => {
await RecruitmentServices.createFaq(batman, 'When was FinishLine created?', 'FinishLine was created in 2019', ner);

await RecruitmentServices.createFaq(batman, 'How many developers are working on FinishLine?', '178 as of 2024', ner);

await AnnouncementService.createAnnouncement(
'Welcome to Finishline!',
[regina.userId],
new Date(),
'Thomas Emrax',
'1',
'software',
ner.organizationId
);
};

performSeed()
Expand Down
46 changes: 46 additions & 0 deletions src/backend/src/services/announcement.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Announcement } from 'shared';
import prisma from '../prisma/prisma';
import { getAnnouncementQueryArgs } from '../prisma-query-args/announcements.query.args';
import announcementTransformer from '../transformers/announcements.transformer';

export default class AnnouncementService {
/**
* Creates an announcement that is sent to users
* this data is populated from slack events
* @param text slack message text
* @param usersReceivedIds users to send announcements to
* @param dateCreated date created of slack message
* @param senderName name of user who sent slack message
* @param slackEventId id of slack event (provided by slack api)
* @param slackChannelName name of channel message was sent in
* @param organizationId id of organization of users
* @returns the created announcement
*/
static async createAnnouncement(
text: string,
usersReceivedIds: string[],
dateCreated: Date,
senderName: string,
slackEventId: string,
slackChannelName: string,
organizationId: string
): Promise<Announcement> {
const announcement = await prisma.announcement.create({
data: {
text,
usersReceived: {
connect: usersReceivedIds.map((id) => ({
userId: id
}))
},
dateCreated,
senderName,
slackEventId,
slackChannelName
},
...getAnnouncementQueryArgs(organizationId)
});

return announcementTransformer(announcement);
}
}
6 changes: 4 additions & 2 deletions src/backend/src/transformers/announcements.transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ const announcementTransformer = (announcement: Prisma.AnnouncementGetPayload<Ann
return {
announcementId: announcement.announcementId,
text: announcement.text,
usersReceived: announcement.usersReceived.map(userTransformer),
dateCreated: announcement.dateCreated,
userCreated: userTransformer(announcement.userCreated),
senderName: announcement.senderName,
slackEventId: announcement.slackEventId,
slackChannelName: announcement.slackChannelName
slackChannelName: announcement.slackChannelName,
dateDeleted: announcement.dateDeleted ?? undefined
};
};

Expand Down
1 change: 1 addition & 0 deletions src/backend/tests/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export const resetUsers = async () => {
await prisma.frequentlyAskedQuestion.deleteMany();
await prisma.organization.deleteMany();
await prisma.user.deleteMany();
await prisma.announcement.deleteMany();
};

export const createFinanceTeamAndLead = async (organization?: Organization) => {
Expand Down
39 changes: 38 additions & 1 deletion src/backend/tests/unmocked/users.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { batmanAppAdmin } from '../test-data/users.test-data';
import UsersService from '../../src/services/users.services';
import { NotFoundException } from '../../src/utils/errors.utils';
import NotificationsService from '../../src/services/notifications.services';
import AnnouncementService from '../../src/services/announcement.service';

describe('User Tests', () => {
let orgId: string;
Expand Down Expand Up @@ -81,7 +82,7 @@ describe('User Tests', () => {
).rejects.toThrow(new NotFoundException('User', '1'));
});

it('Succeeds and gets user notifications', async () => {
it('Succeeds and removes user notification', async () => {
const testBatman = await createTestUser(batmanAppAdmin, orgId);
await NotificationsService.sendNotifcationToUsers('test1', 'test1', [testBatman.userId], orgId);
await NotificationsService.sendNotifcationToUsers('test2', 'test2', [testBatman.userId], orgId);
Expand All @@ -102,4 +103,40 @@ describe('User Tests', () => {
expect(updatedNotifications[0].text).toBe('test2');
});
});

describe('Get Announcements', () => {
it('fails on invalid user id', async () => {
await expect(async () => await UsersService.getUserUnreadAnnouncements('1', organization)).rejects.toThrow(
new NotFoundException('User', '1')
);
});

it('Succeeds and gets user announcements', async () => {
const testBatman = await createTestUser(batmanAppAdmin, orgId);
await AnnouncementService.createAnnouncement(
'test1',
[testBatman.userId],
new Date(),
'Thomas Emrax',
'1',
'software',
organization.organizationId
);
await AnnouncementService.createAnnouncement(
'test2',
[testBatman.userId],
new Date(),
'Superman',
'50',
'mechanical',
organization.organizationId
);

const announcements = await UsersService.getUserUnreadAnnouncements(testBatman.userId, organization);

expect(announcements).toHaveLength(2);
expect(announcements[0].text).toBe('test1');
expect(announcements[1].text).toBe('test2');
});
});
});
4 changes: 3 additions & 1 deletion src/shared/src/types/announcements.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import { User } from './user-types';
export interface Announcement {
announcementId: string;
text: string;
userCreated: User;
usersReceived: User[];
senderName: string;
dateCreated: Date;
slackEventId: string;
slackChannelName: string;
dateDeleted?: Date;
}

0 comments on commit 763183f

Please sign in to comment.