diff --git a/prisma/migrations/20240813012053_/migration.sql b/prisma/migrations/20240813012053_/migration.sql new file mode 100644 index 0000000..696152d --- /dev/null +++ b/prisma/migrations/20240813012053_/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "shelters" ADD COLUMN "authorizedContact" BOOLEAN DEFAULT false; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 1a4b82f..f73cd54 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -110,27 +110,28 @@ model Supply { } model Shelter { - id String @id @default(uuid()) - name String @unique - pix String? @unique - address String - street String? - neighbourhood String? - city String? - streetNumber String? @map("street_number") - zipCode String? @map("zip_code") - petFriendly Boolean? @map("pet_friendly") - shelteredPeople Int? @map("sheltered_people") - capacity Int? - contact String? - prioritySum Int @default(value: 0) @map("priority_sum") - latitude Float? - longitude Float? - verified Boolean @default(value: false) - category ShelterCategory @default(value: Shelter) - actived Boolean @default(value: true) - createdAt String @map("created_at") @db.VarChar(32) - updatedAt String? @map("updated_at") @db.VarChar(32) + id String @id @default(uuid()) + name String @unique + pix String? @unique + address String + street String? + neighbourhood String? + city String? + streetNumber String? @map("street_number") + zipCode String? @map("zip_code") + petFriendly Boolean? @map("pet_friendly") + shelteredPeople Int? @map("sheltered_people") + authorizedContact Boolean? @default(value: false) + capacity Int? + contact String? + prioritySum Int @default(value: 0) @map("priority_sum") + latitude Float? + longitude Float? + verified Boolean @default(value: false) + category ShelterCategory @default(value: Shelter) + actived Boolean @default(value: true) + createdAt String @map("created_at") @db.VarChar(32) + updatedAt String? @map("updated_at") @db.VarChar(32) shelterManagers ShelterManagers[] shelterSupplies ShelterSupply[] diff --git a/src/shelter/ShelterSearch.ts b/src/shelter/ShelterSearch.ts index 3434413..ed07b06 100644 --- a/src/shelter/ShelterSearch.ts +++ b/src/shelter/ShelterSearch.ts @@ -204,6 +204,9 @@ function parseTagResponse( }; const parsed = results.map((result) => { + if (!result.authorizedContact) { + result.contact = 'Não autorizado informar'; + } return { ...result, shelterSupplies: result.shelterSupplies.reduce((prev, shelterSupply) => { diff --git a/src/shelter/shelter.service.spec.ts b/src/shelter/shelter.service.spec.ts index 1ce3198..142b9aa 100644 --- a/src/shelter/shelter.service.spec.ts +++ b/src/shelter/shelter.service.spec.ts @@ -1,13 +1,15 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ShelterService } from './shelter.service'; import { PrismaService } from 'src/prisma/prisma.service'; +import { ShelterCategory } from '@prisma/client'; describe('ShelterService', () => { let service: ShelterService; + let prismaService: PrismaService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [ShelterService], + providers: [ShelterService, PrismaService], }) .useMocker((token) => { if (token === PrismaService) { @@ -15,15 +17,269 @@ describe('ShelterService', () => { supplyCategory: { findMany: jest.fn().mockResolvedValue([]), }, + shelter: { + findFirst: jest.fn(), + findMany: jest.fn(), + count: jest.fn(), + }, }; } }) .compile(); service = module.get(ShelterService); + prismaService = module.get(PrismaService); }); it('should be defined', () => { expect(service).toBeDefined(); }); + + describe('ShelterService - show method', () => { + it('should return data with contact hidden when authorizedContact is false and shouldShowContact is false', async () => { + const mockShelterData = { + id: '1', + name: 'Test Shelter', + pix: '12345678901234567890', + address: 'Test Address', + street: 'Test Street', + neighbourhood: 'Test Neighbourhood', + city: 'Test City', + streetNumber: '123', + zipCode: '12345-678', + petFriendly: true, + shelteredPeople: 50, + authorizedContact: false, + capacity: 100, + contact: '123456789', + prioritySum: 5, + latitude: -23.55052, + longitude: -46.633308, + verified: true, + category: ShelterCategory.Shelter, + actived: true, + createdAt: '2024-08-12T12:00:00Z', + updatedAt: '2024-08-13T12:00:00Z', + shelterManagers: [], + shelterSupplies: [], + supplyHistories: [], + donationOrders: [], + shelterUsers: [], + }; + + jest + .spyOn(prismaService.shelter, 'findFirst') + .mockResolvedValueOnce(mockShelterData); + + const result = await service.show('1', false); + expect(result).not.toBeNull(); + expect(result!.contact).toBe('Não autorizado informar'); + }); + + it('should return data with contact visible when authorizedContact is true or shouldShowContact is true', async () => { + const mockShelterData = { + id: '1', + name: 'Test Shelter', + pix: '12345678901234567890', + address: 'Test Address', + street: 'Test Street', + neighbourhood: 'Test Neighbourhood', + city: 'Test City', + streetNumber: '123', + zipCode: '12345-678', + petFriendly: true, + shelteredPeople: 50, + authorizedContact: true, + capacity: 100, + contact: '123456789', + prioritySum: 5, + latitude: -23.55052, + longitude: -46.633308, + verified: true, + category: ShelterCategory.Shelter, + actived: true, + createdAt: '2024-08-12T12:00:00Z', + updatedAt: '2024-08-13T12:00:00Z', + shelterManagers: [], + shelterSupplies: [], + supplyHistories: [], + donationOrders: [], + shelterUsers: [], + }; + + jest + .spyOn(prismaService.shelter, 'findFirst') + .mockResolvedValueOnce(mockShelterData); + + const result = await service.show('1', true); + expect(result).not.toBeNull(); + expect(result!.contact).toBe('123456789'); + }); + + it('should return data with contact visible when shouldShowContact is true and authorizedContact is false', async () => { + const mockShelterData = { + id: '1', + name: 'Test Shelter', + pix: '12345678901234567890', + address: 'Test Address', + street: 'Test Street', + neighbourhood: 'Test Neighbourhood', + city: 'Test City', + streetNumber: '123', + zipCode: '12345-678', + petFriendly: true, + shelteredPeople: 50, + authorizedContact: false, + capacity: 100, + contact: '123456789', + prioritySum: 5, + latitude: -23.55052, + longitude: -46.633308, + verified: true, + category: ShelterCategory.Shelter, + actived: true, + createdAt: '2024-08-12T12:00:00Z', + updatedAt: '2024-08-13T12:00:00Z', + shelterManagers: [], + shelterSupplies: [], + supplyHistories: [], + donationOrders: [], + shelterUsers: [], + }; + + jest + .spyOn(prismaService.shelter, 'findFirst') + .mockResolvedValueOnce(mockShelterData); + + const result = await service.show('1', true); + expect(result).not.toBeNull(); + expect(result!.contact).toBe('123456789'); + }); + }); + + describe('ShelterService - index method', () => { + it('should return shelters with contacts hidden when authorizedContact is false', async () => { + const mockShelterData = [ + { + id: '1', + name: 'Test Shelter', + pix: '12345678901234567890', + address: 'Test Address', + street: 'Test Street', + neighbourhood: 'Test Neighbourhood', + city: 'Test City', + streetNumber: '123', + zipCode: '12345-678', + petFriendly: true, + shelteredPeople: 50, + authorizedContact: false, + capacity: 100, + contact: '123456789', + prioritySum: 5, + latitude: -23.55052, + longitude: -46.633308, + verified: true, + category: ShelterCategory.Shelter, + actived: true, + createdAt: '2024-08-12T12:00:00Z', + updatedAt: '2024-08-13T12:00:00Z', + shelterManagers: [], + shelterSupplies: [], + supplyHistories: [], + donationOrders: [], + shelterUsers: [], + }, + ]; + + jest + .spyOn(prismaService.shelter, 'findMany') + .mockResolvedValueOnce(mockShelterData); + jest.spyOn(prismaService.shelter, 'count').mockResolvedValueOnce(1); + + const query = { + order: 'asc', + orderBy: 'name', + page: 1, + perPage: 10, + search: '', + }; + + const result = await service.index(query); + + result.results.forEach((shelter) => { + expect(shelter.contact).toBe('Não autorizado informar'); + }); + }); + + it('should return shelters with contacts visible when authorizedContact is true', async () => { + const mockShelterData = [ + { + id: '1', + name: 'Test Shelter', + pix: '12345678901234567890', + address: 'Test Address', + street: 'Test Street', + neighbourhood: 'Test Neighbourhood', + city: 'Test City', + streetNumber: '123', + zipCode: '12345-678', + petFriendly: true, + shelteredPeople: 50, + authorizedContact: true, + capacity: 100, + contact: '123456789', + prioritySum: 5, + latitude: -23.55052, + longitude: -46.633308, + verified: true, + category: ShelterCategory.Shelter, + actived: true, + createdAt: '2024-08-12T12:00:00Z', + updatedAt: '2024-08-13T12:00:00Z', + shelterManagers: [], + shelterSupplies: [], + supplyHistories: [], + donationOrders: [], + shelterUsers: [], + }, + ]; + + jest + .spyOn(prismaService.shelter, 'findMany') + .mockResolvedValueOnce(mockShelterData); + jest.spyOn(prismaService.shelter, 'count').mockResolvedValueOnce(1); + + const query = { + order: 'asc', + orderBy: 'name', + page: 1, + perPage: 10, + search: '', + }; + + const result = await service.index(query); + + result.results.forEach((shelter) => { + expect(shelter.contact).toBe('123456789'); + }); + }); + + it('should return an empty list when no shelters match the query', async () => { + jest.spyOn(prismaService.shelter, 'findMany').mockResolvedValueOnce([]); + jest.spyOn(prismaService.shelter, 'count').mockResolvedValueOnce(0); + + const query = { + order: 'asc', + orderBy: 'name', + page: 1, + perPage: 10, + search: '', + }; + + const result = await service.index(query); + + expect(result.results).toEqual([]); + expect(result.count).toBe(0); + }); + }); }); diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index 9aee0f0..41e4f85 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -84,13 +84,14 @@ export class ShelterService implements OnModuleInit { pix: true, shelteredPeople: true, capacity: true, - contact: shouldShowContact, + contact: true, petFriendly: true, prioritySum: true, latitude: true, longitude: true, verified: true, actived: true, + authorizedContact: true, category: true, shelterSupplies: { select: { @@ -122,7 +123,15 @@ export class ShelterService implements OnModuleInit { }, }); - if (data) this.decayShelterSupply(data.shelterSupplies); + if (data) { + this.decayShelterSupply(data.shelterSupplies); + + if (!shouldShowContact && !data.authorizedContact) { + data.contact = 'Não autorizado informar'; + } else if (shouldShowContact && !data.authorizedContact) { + return data; + } + } return data; } @@ -150,7 +159,6 @@ export class ShelterService implements OnModuleInit { orderBy: { [orderBy]: order }, where, }; - const results = await this.prismaService.shelter.findMany({ ...whereData, select: { @@ -174,6 +182,8 @@ export class ShelterService implements OnModuleInit { category: true, createdAt: true, updatedAt: true, + contact: true, + authorizedContact: true, shelterSupplies: { where: { priority: { diff --git a/src/shelter/types/search.types.ts b/src/shelter/types/search.types.ts index 1e5f273..20775f0 100644 --- a/src/shelter/types/search.types.ts +++ b/src/shelter/types/search.types.ts @@ -48,7 +48,7 @@ export const ShelterSearchPropsSchema = z.object({ export type ShelterSearchProps = z.infer; -type AllowedShelterFields = Omit; +type AllowedShelterFields = Shelter; export type SearchShelterTagResponse = AllowedShelterFields & { shelterSupplies: (ShelterSupply & { supply: Supply })[]; diff --git a/src/shelter/types/types.ts b/src/shelter/types/types.ts index c236178..ad1abd4 100644 --- a/src/shelter/types/types.ts +++ b/src/shelter/types/types.ts @@ -24,6 +24,7 @@ const ShelterSchema = z.object({ longitude: z.number().nullable().optional(), capacity: z.number().min(0).nullable().optional(), contact: z.string().nullable().optional(), + authorizedContact: z.boolean().optional(), verified: z.boolean(), createdAt: z.string(), updatedAt: z.string().nullable().optional(), @@ -39,6 +40,7 @@ const CreateShelterSchema = ShelterSchema.omit({ const UpdateShelterSchema = ShelterSchema.pick({ petFriendly: true, shelteredPeople: true, + authorizedContact: true, }).partial(); const FullUpdateShelterSchema = ShelterSchema.omit({