Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/backend/src/config/typeorm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { RemoveMultipleVolunteerTypes1764811878152 } from '../migrations/1764811
import { RemoveUnusedStatuses1764816885341 } from '../migrations/1764816885341-RemoveUnusedStatuses';
import { UpdatePantryFields1763762628431 } from '../migrations/1763762628431-UpdatePantryFields';
import { PopulateDummyData1768501812134 } from '../migrations/1768501812134-populateDummyData';
import { AddDonationRecurranceFields1770080947285 } from '../migrations/1770080947285-AddDonationRecurranceFields';

const config = {
type: 'postgres',
Expand Down Expand Up @@ -67,6 +68,7 @@ const config = {
RemoveMultipleVolunteerTypes1764811878152,
RemoveUnusedStatuses1764816885341,
PopulateDummyData1768501812134,
AddDonationRecurranceFields1770080947285,
],
};

Expand Down
32 changes: 31 additions & 1 deletion apps/backend/src/donations/donations.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import { ApiBody } from '@nestjs/swagger';
import { Donation } from './donations.entity';
import { DonationService } from './donations.service';
import { DonationStatus } from './types';
import { DonationStatus, RecourranceEnum } from './types';

@Controller('donations')
export class DonationsController {
Expand Down Expand Up @@ -54,6 +54,20 @@ export class DonationsController {
totalItems: { type: 'integer', example: 100 },
totalOz: { type: 'integer', example: 500 },
totalEstimatedValue: { type: 'integer', example: 1000 },
recurrance: {
type: 'string',
enum: Object.values(RecourranceEnum),
example: RecourranceEnum.ONCE,
nullable: true,
},
recurranceFreq: { type: 'integer', example: 1, nullable: true },
nextDonationDates: {
type: 'array',
items: { type: 'string', format: 'date-time' },
example: ['2024-07-01T00:00:00Z', '2024-08-01T00:00:00Z'],
nullable: true,
},
occurances: { type: 'integer', example: 2, nullable: true },
},
},
})
Expand All @@ -66,6 +80,10 @@ export class DonationsController {
totalItems: number;
totalOz: number;
totalEstimatedValue: number;
recurrance: RecourranceEnum;
recurranceFreq?: number;
nextDonationDates?: Date[];
occurances?: number;
},
): Promise<Donation> {
if (
Expand All @@ -74,13 +92,25 @@ export class DonationsController {
) {
throw new BadRequestException('Invalid status');
}
// If we got a recurrance, we should have all of these values
// The next donation dates should be a list of dates we will get from the frontend accordingly
if (
body.recurrance != RecourranceEnum.ONCE &&
(!body.recurranceFreq || !body.nextDonationDates || !body.occurances)
) {
throw new BadRequestException('Recurrance details are incomplete');
}
return this.donationService.create(
body.foodManufacturerId,
body.dateDonated,
body.status ?? DonationStatus.AVAILABLE,
body.totalItems,
body.totalOz,
body.totalEstimatedValue,
body.recurrance,
body.recurranceFreq ?? null,
body.nextDonationDates ?? null,
body.occurances ?? null,
);
}

Expand Down
25 changes: 24 additions & 1 deletion apps/backend/src/donations/donations.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
ManyToOne,
} from 'typeorm';
import { FoodManufacturer } from '../foodManufacturers/manufacturer.entity';
import { DonationStatus } from './types';
import { DonationStatus, RecourranceEnum } from './types';

@Entity('donations')
export class Donation {
Expand Down Expand Up @@ -44,4 +44,27 @@ export class Donation {

@Column({ name: 'total_estimated_value', type: 'int', nullable: true })
totalEstimatedValue: number;

@Column({
name: 'recurrance',
type: 'enum',
enum: RecourranceEnum,
enumName: 'donation_recurrance_enum',
default: RecourranceEnum.ONCE,
})
recurrance: RecourranceEnum;

@Column({ name: 'recurrance_freq', type: 'int', nullable: true })
recurranceFreq: number;

@Column({
name: 'next_donation_dates',
type: 'timestamptz',
array: true,
nullable: true,
})
nextDonationDates: Date[];

@Column({ name: 'occurances', type: 'int', nullable: true })
occurances: number;
}
12 changes: 10 additions & 2 deletions apps/backend/src/donations/donations.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Repository } from 'typeorm';
import { Donation } from './donations.entity';
import { validateId } from '../utils/validation.utils';
import { FoodManufacturer } from '../foodManufacturers/manufacturer.entity';
import { DonationStatus } from './types';
import { DonationStatus, RecourranceEnum } from './types';

@Injectable()
export class DonationService {
Expand Down Expand Up @@ -45,7 +45,11 @@ export class DonationService {
totalItems: number,
totalOz: number,
totalEstimatedValue: number,
) {
recurrance: RecourranceEnum,
recurranceFreq: number,
nextDonationDates: Date[] | null,
occurances: number | null,
): Promise<Donation> {
validateId(foodManufacturerId, 'Food Manufacturer');
const manufacturer = await this.manufacturerRepo.findOne({
where: { foodManufacturerId },
Expand All @@ -63,6 +67,10 @@ export class DonationService {
totalItems,
totalOz,
totalEstimatedValue,
recurrance,
recurranceFreq,
nextDonationDates,
occurances,
});

return this.repo.save(donation);
Expand Down
7 changes: 7 additions & 0 deletions apps/backend/src/donations/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@ export enum DonationStatus {
FULFILLED = 'fulfilled',
MATCHING = 'matching',
}

export enum RecourranceEnum {
ONCE = 'once',
WEEKLY = 'weekly',
MONTHLY = 'monthly',
YEARLY = 'yearly',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddDonationRecurranceFields1770080947285
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TYPE donation_recurrance_enum AS ENUM (
'once',
'weekly',
'monthly',
'yearly'
);
`);

await queryRunner.query(`
ALTER TABLE donations
ADD COLUMN recurrance donation_recurrance_enum NOT NULL DEFAULT 'once',
ADD COLUMN recurrance_freq INTEGER,
ADD COLUMN next_donation_dates TIMESTAMP WITH TIME ZONE[],
ADD COLUMN occurances INTEGER;
`);

await queryRunner.query(`
ALTER TABLE donations
ADD CONSTRAINT recurrance_fields_not_null CHECK (
(recurrance = 'once'
AND recurrance_freq IS NULL
AND next_donation_dates IS NULL
AND occurances IS NULL)
OR
(recurrance != 'once'
AND recurrance_freq IS NOT NULL
AND next_donation_dates IS NOT NULL
AND occurances IS NOT NULL)
);
`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE donations
DROP CONSTRAINT recurrance_fields_not_null,
DROP COLUMN recurrance,
DROP COLUMN recurrance_freq,
DROP COLUMN next_donation_dates,
DROP COLUMN occurances;

DROP TYPE donation_recurrance_enum;
`);
}
}
7 changes: 7 additions & 0 deletions apps/frontend/src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ export enum DonationStatus {
MATCHING = 'matching',
}

export enum RecourranceEnum {
ONCE = 'once',
WEEKLY = 'weekly',
MONTHLY = 'monthly',
YEARLY = 'yearly',
}

export interface Donation {
donationId: number;
dateDonated: string;
Expand Down
Loading