From 15e5ba3cafa30beeb4df42cc74ba4a29026a953c Mon Sep 17 00:00:00 2001 From: Garamon Date: Sun, 6 Oct 2024 23:07:46 -0400 Subject: [PATCH 1/4] filter logic --- apps/backend/src/app.module.ts | 2 + apps/backend/src/donations/donation.entity.ts | 27 ++++++++++ .../src/donations/donations.controller.ts | 54 +++++++++++++++++++ .../backend/src/donations/donations.module.ts | 12 +++++ .../src/donations/donations.service.ts | 45 ++++++++++++++++ .../src/donations/dto/create-donation.dto.ts | 1 + .../src/donations/dto/filter-donations.dto.ts | 16 ++++++ .../src/donations/dto/update-donation.dto.ts | 4 ++ apps/backend/src/donations/types.ts | 4 ++ 9 files changed, 165 insertions(+) create mode 100644 apps/backend/src/donations/donation.entity.ts create mode 100644 apps/backend/src/donations/donations.controller.ts create mode 100644 apps/backend/src/donations/donations.module.ts create mode 100644 apps/backend/src/donations/donations.service.ts create mode 100644 apps/backend/src/donations/dto/create-donation.dto.ts create mode 100644 apps/backend/src/donations/dto/filter-donations.dto.ts create mode 100644 apps/backend/src/donations/dto/update-donation.dto.ts create mode 100644 apps/backend/src/donations/types.ts diff --git a/apps/backend/src/app.module.ts b/apps/backend/src/app.module.ts index 8fc31d7..1015fbb 100644 --- a/apps/backend/src/app.module.ts +++ b/apps/backend/src/app.module.ts @@ -6,6 +6,7 @@ import { AppService } from './app.service'; import { UsersModule } from './users/users.module'; import { AuthModule } from './auth/auth.module'; import { ConfigModule, ConfigService } from '@nestjs/config'; +import { DonationsModule } from './donations/donations.module'; import typeorm from './config/typeorm'; @Module({ @@ -22,6 +23,7 @@ import typeorm from './config/typeorm'; }), UsersModule, AuthModule, + DonationsModule, ], controllers: [AppController], providers: [AppService], diff --git a/apps/backend/src/donations/donation.entity.ts b/apps/backend/src/donations/donation.entity.ts new file mode 100644 index 0000000..01c2614 --- /dev/null +++ b/apps/backend/src/donations/donation.entity.ts @@ -0,0 +1,27 @@ +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { DonationStatus } from './types'; + +@Entity() +export class Donation { + @PrimaryGeneratedColumn() + id: number; + + @Column({ type: 'text', array: true }) //FIX + restrictions: string[]; + + @Column({ type: 'timestamp' }) + due_date: Date; + + @Column({ type: 'int' }) + pantry_id: number; + + //@Column({ type: 'varchar', length: 50 }) + @Column({ type: 'enum', enum: DonationStatus }) + status: string; + + @Column({ type: 'text', nullable: true }) + feedback: string; + + @Column({ type: 'json' }) + contents: JSON; +} diff --git a/apps/backend/src/donations/donations.controller.ts b/apps/backend/src/donations/donations.controller.ts new file mode 100644 index 0000000..029ee7b --- /dev/null +++ b/apps/backend/src/donations/donations.controller.ts @@ -0,0 +1,54 @@ +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, + UseGuards, +} from '@nestjs/common'; +import { DonationsService } from './donations.service'; +import { CreateDonationDto } from './dto/create-donation.dto'; +import { UpdateDonationDto } from './dto/update-donation.dto'; +import { FilterDonationsDto } from './dto/filter-donations.dto'; +import { AuthGuard } from '@nestjs/passport'; + +@Controller('donations') +export class DonationsController { + constructor(private readonly donationsService: DonationsService) {} + + @Post() + create(@Body() createDonationDto: CreateDonationDto) { + return this.donationsService.create(createDonationDto); + } + + @Get() + findAll() { + return this.donationsService.findAll(); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.donationsService.findOne(+id); + } + + @Patch(':id') + update( + @Param('id') id: string, + @Body() updateDonationDto: UpdateDonationDto, + ) { + return this.donationsService.update(+id, updateDonationDto); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.donationsService.remove(+id); + } + + @UseGuards(AuthGuard('jwt')) + @Get('/orders') + filter(@Body() filterDonationsDto: FilterDonationsDto) { + return this.donationsService.filter(filterDonationsDto); + } +} diff --git a/apps/backend/src/donations/donations.module.ts b/apps/backend/src/donations/donations.module.ts new file mode 100644 index 0000000..7284817 --- /dev/null +++ b/apps/backend/src/donations/donations.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { DonationsService } from './donations.service'; +import { DonationsController } from './donations.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Donation } from './donation.entity'; + +@Module({ + imports: [TypeOrmModule.forFeature([Donation])], + controllers: [DonationsController], + providers: [DonationsService], +}) +export class DonationsModule {} diff --git a/apps/backend/src/donations/donations.service.ts b/apps/backend/src/donations/donations.service.ts new file mode 100644 index 0000000..22d251c --- /dev/null +++ b/apps/backend/src/donations/donations.service.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { CreateDonationDto } from './dto/create-donation.dto'; +import { UpdateDonationDto } from './dto/update-donation.dto'; +import { FilterDonationsDto } from './dto/filter-donations.dto'; +import { Donation } from './donation.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository, Between, In } from 'typeorm'; + +@Injectable() +export class DonationsService { + constructor(@InjectRepository(Donation) private repo: Repository) {} + + create(createDonationDto: CreateDonationDto) { + return 'This action adds a new donation'; + } + + findAll() { + return `This action returns all donations`; + } + + findOne(id: number) { + return `This action returns a #${id} donation`; + } + + update(id: number, updateDonationDto: UpdateDonationDto) { + return `This action updates a #${id} donation`; + } + + remove(id: number) { + return `This action removes a #${id} donation`; + } + + filter(filterDonationsDto: FilterDonationsDto) { + return this.repo.find({ + where: { + pantry_id: In(filterDonationsDto.pantry_ids), + status: filterDonationsDto.status, + due_date: Between( + filterDonationsDto.due_date_start, + filterDonationsDto.due_date_end, + ), + }, + }); + } +} diff --git a/apps/backend/src/donations/dto/create-donation.dto.ts b/apps/backend/src/donations/dto/create-donation.dto.ts new file mode 100644 index 0000000..538847f --- /dev/null +++ b/apps/backend/src/donations/dto/create-donation.dto.ts @@ -0,0 +1 @@ +export class CreateDonationDto {} diff --git a/apps/backend/src/donations/dto/filter-donations.dto.ts b/apps/backend/src/donations/dto/filter-donations.dto.ts new file mode 100644 index 0000000..9540cbf --- /dev/null +++ b/apps/backend/src/donations/dto/filter-donations.dto.ts @@ -0,0 +1,16 @@ +import { IsDate, IsEnum, IsInt } from 'class-validator'; +import { DonationStatus } from '../types'; + +export class FilterDonationsDto { + @IsDate() + due_date_start: Date; + + @IsDate() + due_date_end: Date; + + @IsInt({ each: true }) + pantry_ids: number[]; + + @IsEnum(DonationStatus) + status: string; +} diff --git a/apps/backend/src/donations/dto/update-donation.dto.ts b/apps/backend/src/donations/dto/update-donation.dto.ts new file mode 100644 index 0000000..7adc23f --- /dev/null +++ b/apps/backend/src/donations/dto/update-donation.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/mapped-types'; +import { CreateDonationDto } from './create-donation.dto'; + +export class UpdateDonationDto extends PartialType(CreateDonationDto) {} diff --git a/apps/backend/src/donations/types.ts b/apps/backend/src/donations/types.ts new file mode 100644 index 0000000..ee4be34 --- /dev/null +++ b/apps/backend/src/donations/types.ts @@ -0,0 +1,4 @@ +export enum DonationStatus { + FULFILLED = 'FULFILLED', + UNFULFILLED = 'UNFULFILLED', +} From 24695e8afdef28524c57c52809fd0fc768bdbca7 Mon Sep 17 00:00:00 2001 From: Garamon Date: Sun, 27 Oct 2024 20:26:38 -0400 Subject: [PATCH 2/4] debugging postgres orm --- apps/backend/src/donations/donation.entity.ts | 4 ++-- apps/backend/src/donations/donations.controller.ts | 13 +++++++------ .../src/donations/dto/filter-donations.dto.ts | 7 ++++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/apps/backend/src/donations/donation.entity.ts b/apps/backend/src/donations/donation.entity.ts index 01c2614..93c0973 100644 --- a/apps/backend/src/donations/donation.entity.ts +++ b/apps/backend/src/donations/donation.entity.ts @@ -1,4 +1,4 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryGeneratedColumn, Timestamp } from 'typeorm'; import { DonationStatus } from './types'; @Entity() @@ -10,7 +10,7 @@ export class Donation { restrictions: string[]; @Column({ type: 'timestamp' }) - due_date: Date; + due_date: Timestamp; @Column({ type: 'int' }) pantry_id: number; diff --git a/apps/backend/src/donations/donations.controller.ts b/apps/backend/src/donations/donations.controller.ts index 029ee7b..171118e 100644 --- a/apps/backend/src/donations/donations.controller.ts +++ b/apps/backend/src/donations/donations.controller.ts @@ -13,11 +13,18 @@ import { CreateDonationDto } from './dto/create-donation.dto'; import { UpdateDonationDto } from './dto/update-donation.dto'; import { FilterDonationsDto } from './dto/filter-donations.dto'; import { AuthGuard } from '@nestjs/passport'; +import { Logger } from '@nestjs/common'; @Controller('donations') export class DonationsController { constructor(private readonly donationsService: DonationsService) {} + @Get('orders') + filter(@Body() filterDonationsDto: FilterDonationsDto) { + console.log('HERE'); + return this.donationsService.filter(filterDonationsDto); + } + @Post() create(@Body() createDonationDto: CreateDonationDto) { return this.donationsService.create(createDonationDto); @@ -45,10 +52,4 @@ export class DonationsController { remove(@Param('id') id: string) { return this.donationsService.remove(+id); } - - @UseGuards(AuthGuard('jwt')) - @Get('/orders') - filter(@Body() filterDonationsDto: FilterDonationsDto) { - return this.donationsService.filter(filterDonationsDto); - } } diff --git a/apps/backend/src/donations/dto/filter-donations.dto.ts b/apps/backend/src/donations/dto/filter-donations.dto.ts index 9540cbf..2870ef3 100644 --- a/apps/backend/src/donations/dto/filter-donations.dto.ts +++ b/apps/backend/src/donations/dto/filter-donations.dto.ts @@ -1,11 +1,12 @@ -import { IsDate, IsEnum, IsInt } from 'class-validator'; +import { IsDate, IsDateString, IsEnum, IsInt } from 'class-validator'; import { DonationStatus } from '../types'; +import { Timestamp } from 'typeorm'; export class FilterDonationsDto { - @IsDate() + @IsDateString() due_date_start: Date; - @IsDate() + @IsDateString() due_date_end: Date; @IsInt({ each: true }) From 1388b4e0cc475d2ac60fb8860ebb55b4221a0945 Mon Sep 17 00:00:00 2001 From: Garamon Date: Sun, 3 Nov 2024 20:07:55 -0500 Subject: [PATCH 3/4] optional filter values --- .../src/donations/donations.controller.ts | 1 - .../src/donations/donations.service.ts | 33 +++++++++++++------ .../src/donations/dto/filter-donations.dto.ts | 12 ++++++- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/apps/backend/src/donations/donations.controller.ts b/apps/backend/src/donations/donations.controller.ts index 171118e..3d819a8 100644 --- a/apps/backend/src/donations/donations.controller.ts +++ b/apps/backend/src/donations/donations.controller.ts @@ -21,7 +21,6 @@ export class DonationsController { @Get('orders') filter(@Body() filterDonationsDto: FilterDonationsDto) { - console.log('HERE'); return this.donationsService.filter(filterDonationsDto); } diff --git a/apps/backend/src/donations/donations.service.ts b/apps/backend/src/donations/donations.service.ts index 22d251c..59fb585 100644 --- a/apps/backend/src/donations/donations.service.ts +++ b/apps/backend/src/donations/donations.service.ts @@ -30,16 +30,29 @@ export class DonationsService { return `This action removes a #${id} donation`; } - filter(filterDonationsDto: FilterDonationsDto) { - return this.repo.find({ - where: { - pantry_id: In(filterDonationsDto.pantry_ids), + async filter(filterDonationsDto: FilterDonationsDto) { + let query = this.repo.createQueryBuilder('donation'); + if (filterDonationsDto.pantry_ids != null) { + query = query.where('donation.pantry_id IN (:...ids)', { + ids: filterDonationsDto.pantry_ids, + }); + } + if (filterDonationsDto.status != null) { + query = query.andWhere('donation.status = :status', { status: filterDonationsDto.status, - due_date: Between( - filterDonationsDto.due_date_start, - filterDonationsDto.due_date_end, - ), - }, - }); + }); + } + if (filterDonationsDto.due_date_start != null) { + query = query.andWhere('donation.due_date >= :start', { + start: filterDonationsDto.due_date_start, + }); + } + if (filterDonationsDto.due_date_end != null) { + query = query.andWhere('donation.due_date <= :end', { + end: filterDonationsDto.due_date_end, + }); + } + const donations = await query.getMany(); + return donations; } } diff --git a/apps/backend/src/donations/dto/filter-donations.dto.ts b/apps/backend/src/donations/dto/filter-donations.dto.ts index 2870ef3..e9315ec 100644 --- a/apps/backend/src/donations/dto/filter-donations.dto.ts +++ b/apps/backend/src/donations/dto/filter-donations.dto.ts @@ -1,17 +1,27 @@ -import { IsDate, IsDateString, IsEnum, IsInt } from 'class-validator'; +import { + IsDate, + IsDateString, + IsEnum, + IsInt, + IsOptional, +} from 'class-validator'; import { DonationStatus } from '../types'; import { Timestamp } from 'typeorm'; export class FilterDonationsDto { @IsDateString() + @IsOptional() due_date_start: Date; @IsDateString() + @IsOptional() due_date_end: Date; @IsInt({ each: true }) + @IsOptional() pantry_ids: number[]; @IsEnum(DonationStatus) + @IsOptional() status: string; } From c03e40ed396350a944b23a7f6d39e054f45dfe31 Mon Sep 17 00:00:00 2001 From: Garamon Date: Mon, 2 Dec 2024 14:32:14 -0500 Subject: [PATCH 4/4] donation status enum update, query instead of body --- apps/backend/src/donations/donations.controller.ts | 4 +++- apps/backend/src/donations/dto/filter-donations.dto.ts | 1 - apps/backend/src/donations/types.ts | 6 ++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/backend/src/donations/donations.controller.ts b/apps/backend/src/donations/donations.controller.ts index 3d819a8..a58275e 100644 --- a/apps/backend/src/donations/donations.controller.ts +++ b/apps/backend/src/donations/donations.controller.ts @@ -7,6 +7,7 @@ import { Param, Delete, UseGuards, + Query, } from '@nestjs/common'; import { DonationsService } from './donations.service'; import { CreateDonationDto } from './dto/create-donation.dto'; @@ -14,13 +15,14 @@ import { UpdateDonationDto } from './dto/update-donation.dto'; import { FilterDonationsDto } from './dto/filter-donations.dto'; import { AuthGuard } from '@nestjs/passport'; import { Logger } from '@nestjs/common'; +import { ValidationPipe } from '@nestjs/common'; @Controller('donations') export class DonationsController { constructor(private readonly donationsService: DonationsService) {} @Get('orders') - filter(@Body() filterDonationsDto: FilterDonationsDto) { + filter(@Query(new ValidationPipe()) filterDonationsDto: FilterDonationsDto) { return this.donationsService.filter(filterDonationsDto); } diff --git a/apps/backend/src/donations/dto/filter-donations.dto.ts b/apps/backend/src/donations/dto/filter-donations.dto.ts index e9315ec..03e6971 100644 --- a/apps/backend/src/donations/dto/filter-donations.dto.ts +++ b/apps/backend/src/donations/dto/filter-donations.dto.ts @@ -6,7 +6,6 @@ import { IsOptional, } from 'class-validator'; import { DonationStatus } from '../types'; -import { Timestamp } from 'typeorm'; export class FilterDonationsDto { @IsDateString() diff --git a/apps/backend/src/donations/types.ts b/apps/backend/src/donations/types.ts index ee4be34..5866f3c 100644 --- a/apps/backend/src/donations/types.ts +++ b/apps/backend/src/donations/types.ts @@ -1,4 +1,6 @@ export enum DonationStatus { - FULFILLED = 'FULFILLED', - UNFULFILLED = 'UNFULFILLED', + REQUESTED = 'REQUESTED', + PROCESSING = 'PROCESSING', + IN_DELIVERY = 'IN_DELIVERY', + RECEIVED = 'RECEIVED', }