Skip to content

Commit 3d93234

Browse files
authored
Merge branch 'main' into jw/ssf-173-fm-donationitem-endpoints
2 parents b4f3a37 + a49f6a6 commit 3d93234

12 files changed

Lines changed: 223 additions & 90 deletions

File tree

apps/backend/src/config/migrations.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { UpdateOrderEntity1769990652833 } from '../migrations/1769990652833-Upda
3333
import { DonationItemFoodTypeNotNull1771524930613 } from '../migrations/1771524930613-DonationItemFoodTypeNotNull';
3434
import { MoveRequestFieldsToOrders1770571145350 } from '../migrations/1770571145350-MoveRequestFieldsToOrders';
3535
import { RenameDonationMatchingStatus1771260403657 } from '../migrations/1771260403657-RenameDonationMatchingStatus';
36+
import { AddAssigneeToOrders1773009000618 } from '../migrations/1773009000618-AddAssigneeToOrders';
3637
import { DropDonationTotalColumns1772241115031 } from '../migrations/1772241115031-DropDonationTotalColumns';
3738
import { FixTrackingLinks1773041840374 } from '../migrations/1773041840374-FixTrackingLinks';
3839
import { CleanupRequestsAndAllocations1771821377918 } from '../migrations/1771821377918-CleanupRequestsAndAllocations';
@@ -75,6 +76,7 @@ const schemaMigrations = [
7576
DonationItemFoodTypeNotNull1771524930613,
7677
MoveRequestFieldsToOrders1770571145350,
7778
RenameDonationMatchingStatus1771260403657,
79+
AddAssigneeToOrders1773009000618,
7880
DropDonationTotalColumns1772241115031,
7981
FixTrackingLinks1773041840374,
8082
CleanupRequestsAndAllocations1771821377918,

apps/backend/src/donationItems/dtos/create-donation-items.dto.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import {
88
IsNotEmpty,
99
Length,
1010
IsOptional,
11+
IsInt,
1112
} from 'class-validator';
12-
import { Type } from 'class-transformer';
13+
import { Transform, Type } from 'class-transformer';
1314
import { FoodType } from '../types';
1415

1516
export class CreateDonationItemDto {
@@ -18,21 +19,30 @@ export class CreateDonationItemDto {
1819
@Length(1, 255)
1920
itemName!: string;
2021

21-
@IsNumber()
22-
@Min(1)
22+
@Transform(({ value }) => parseInt(value, 10))
23+
@IsInt({ message: 'Quantity must be an integer value' })
24+
@Min(1, { message: 'Quantity must be at least 1' })
2325
quantity!: number;
2426

25-
@IsNumber()
27+
@IsInt()
2628
@Min(0)
2729
reservedQuantity!: number;
2830

29-
@IsNumber()
30-
@Min(0.01)
31+
@Transform(({ value }) => parseFloat(value))
32+
@IsNumber(
33+
{ maxDecimalPlaces: 2 },
34+
{ message: 'Oz per item must have at most 2 decimal places' },
35+
)
36+
@Min(0.01, { message: 'Oz per item must be at least 0.01' })
3137
@IsOptional()
3238
ozPerItem?: number;
3339

34-
@IsNumber()
35-
@Min(0.01)
40+
@Transform(({ value }) => parseFloat(value))
41+
@IsNumber(
42+
{ maxDecimalPlaces: 2 },
43+
{ message: 'Estimated value must have at most 2 decimal places' },
44+
)
45+
@Min(0.01, { message: 'Estimated value must be at least 0.01' })
3646
@IsOptional()
3747
estimatedValue?: number;
3848

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { MigrationInterface, QueryRunner } from 'typeorm';
2+
3+
export class AddAssigneeToOrders1773009000618 implements MigrationInterface {
4+
public async up(queryRunner: QueryRunner): Promise<void> {
5+
await queryRunner.query(`ALTER TABLE orders ADD COLUMN assignee_id INT`);
6+
7+
await queryRunner.query(`
8+
UPDATE orders o SET assignee_id = (
9+
SELECT va.volunteer_id FROM volunteer_assignments va
10+
JOIN food_requests fr ON fr.pantry_id = va.pantry_id
11+
WHERE fr.request_id = o.request_id
12+
LIMIT 1
13+
)
14+
`);
15+
16+
await queryRunner.query(`
17+
ALTER TABLE orders
18+
ALTER COLUMN assignee_id SET NOT NULL,
19+
ADD CONSTRAINT fk_assignee_id FOREIGN KEY (assignee_id) REFERENCES users(user_id) ON DELETE RESTRICT
20+
`);
21+
}
22+
23+
public async down(queryRunner: QueryRunner): Promise<void> {
24+
await queryRunner.query(`
25+
ALTER TABLE orders
26+
DROP CONSTRAINT IF EXISTS fk_assignee_id,
27+
DROP COLUMN assignee_id
28+
`);
29+
}
30+
}

apps/backend/src/orders/order.entity.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { FoodRequest } from '../foodRequests/request.entity';
1111
import { FoodManufacturer } from '../foodManufacturers/manufacturers.entity';
1212
import { OrderStatus } from './types';
1313
import { Allocation } from '../allocations/allocations.entity';
14+
import { User } from '../users/users.entity';
1415

1516
@Entity('orders')
1617
export class Order {
@@ -99,4 +100,11 @@ export class Order {
99100
},
100101
})
101102
shippingCost!: number | null;
103+
104+
@ManyToOne(() => User, { nullable: false, onDelete: 'RESTRICT' })
105+
@JoinColumn({ name: 'assignee_id' })
106+
assignee!: User;
107+
108+
@Column({ name: 'assignee_id', type: 'int' })
109+
assigneeId!: number;
102110
}

apps/backend/src/orders/order.service.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,6 @@ describe('OrdersService', () => {
578578
it('should update order with delivery details and set status to delivered but request remains active', async () => {
579579
const orderRepo = testDataSource.getRepository(Order);
580580
const requestRepo = testDataSource.getRepository(FoodRequest);
581-
582581
// Get an existing shipped order
583582
const existingShippedOrder = await orderRepo.findOne({
584583
where: { status: OrderStatus.SHIPPED },
@@ -594,6 +593,7 @@ describe('OrdersService', () => {
594593
const secondOrder = orderRepo.create({
595594
requestId: existingShippedOrder.requestId,
596595
foodManufacturerId: existingShippedOrder.foodManufacturerId,
596+
assigneeId: existingShippedOrder.assigneeId,
597597
status: OrderStatus.SHIPPED,
598598
shippedAt: new Date(),
599599
});

apps/backend/src/orders/order.service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class OrdersService {
3131
.createQueryBuilder('order')
3232
.leftJoinAndSelect('order.request', 'request')
3333
.leftJoinAndSelect('request.pantry', 'pantry')
34-
.leftJoinAndSelect('pantry.volunteers', 'volunteers')
34+
.leftJoinAndSelect('order.assignee', 'assignee')
3535
.select([
3636
'order.orderId',
3737
'order.status',
@@ -40,9 +40,9 @@ export class OrdersService {
4040
'order.deliveredAt',
4141
'request.pantryId',
4242
'pantry.pantryName',
43-
'volunteers.id',
44-
'volunteers.firstName',
45-
'volunteers.lastName',
43+
'assignee.id',
44+
'assignee.firstName',
45+
'assignee.lastName',
4646
]);
4747

4848
if (filters?.status) {

apps/backend/src/users/users.service.spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,11 @@ describe('UsersService', () => {
232232

233233
describe('remove', () => {
234234
it('should remove a user by id', async () => {
235+
await testDataSource.query(
236+
`DELETE FROM allocations WHERE order_id IN (SELECT order_id FROM orders WHERE assignee_id = 6)`,
237+
);
238+
await testDataSource.query(`DELETE FROM orders WHERE assignee_id = 6`);
239+
235240
const result = await service.remove(6);
236241

237242
expect(result.email).toBe('james.t@volunteer.org');

apps/backend/src/volunteers/volunteers.service.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ describe('VolunteersService', () => {
139139

140140
describe('getVolunteersAndPantryAssignments', () => {
141141
it('returns an empty array when there are no volunteers', async () => {
142-
// Delete all users with role 'volunteer' (CASCADE will handle related data)
142+
await testDataSource.query(`DELETE FROM allocations`);
143+
await testDataSource.query(`DELETE FROM orders`);
143144
await testDataSource.query(
144145
`DELETE FROM "users" WHERE role = 'volunteer'`,
145146
);

apps/frontend/src/chakra-ui.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ declare module '@chakra-ui/react' {
7878
export interface NativeSelectFieldProps
7979
extends ComponentPropsLenientChildren {}
8080

81+
// Tooltip components
82+
export interface TooltipTriggerProps extends ComponentPropsLenientChildren {}
83+
export interface TooltipPositionerProps
84+
extends ComponentPropsLenientChildren {}
85+
export interface TooltipContentProps extends ComponentPropsLenientChildren {}
86+
8187
// Common components
8288
export interface ButtonProps extends ComponentPropsStrictChildren {}
8389
export interface IconButtonProps extends ComponentPropsStrictChildren {}

0 commit comments

Comments
 (0)