diff --git a/apps/backend/src/config/migrations.ts b/apps/backend/src/config/migrations.ts index 9e6387203..b49a45983 100644 --- a/apps/backend/src/config/migrations.ts +++ b/apps/backend/src/config/migrations.ts @@ -42,6 +42,7 @@ import { AddDonationItemConfirmation1774140453305 } from '../migrations/17741404 import { DonationItemsOnDeleteCascade1774214910101 } from '../migrations/1774214910101-DonationItemsOnDeleteCascade'; import { OrdersVolunteerActions1774883880543 } from '../migrations/1774883880543-OrdersVolunteerActions'; import { AddUserActiveField1780531200000 } from '../migrations/1780531200000-AddUserActiveField'; +import { MakeDonationItemDetailsRequired1782000000000 } from '../migrations/1782000000000-MakeDonationItemDetailsRequired'; const schemaMigrations = [ User1725726359198, @@ -88,6 +89,7 @@ const schemaMigrations = [ DonationItemsOnDeleteCascade1774214910101, OrdersVolunteerActions1774883880543, AddUserActiveField1780531200000, + MakeDonationItemDetailsRequired1782000000000, ]; export default schemaMigrations; diff --git a/apps/backend/src/donationItems/donationItems.entity.ts b/apps/backend/src/donationItems/donationItems.entity.ts index 9b8fd8061..d84a57a7d 100644 --- a/apps/backend/src/donationItems/donationItems.entity.ts +++ b/apps/backend/src/donationItems/donationItems.entity.ts @@ -31,11 +31,11 @@ export class DonationItem { @Column({ name: 'reserved_quantity', type: 'int', default: 0 }) reservedQuantity!: number; - @Column({ name: 'oz_per_item', type: 'numeric', nullable: true }) - ozPerItem!: number | null; + @Column({ name: 'oz_per_item', type: 'numeric' }) + ozPerItem!: number; - @Column({ name: 'estimated_value', type: 'numeric', nullable: true }) - estimatedValue!: number | null; + @Column({ name: 'estimated_value', type: 'numeric' }) + estimatedValue!: number; @Column({ name: 'food_type', diff --git a/apps/backend/src/donationItems/donationItems.service.spec.ts b/apps/backend/src/donationItems/donationItems.service.spec.ts index cad8b0783..37054660e 100644 --- a/apps/backend/src/donationItems/donationItems.service.spec.ts +++ b/apps/backend/src/donationItems/donationItems.service.spec.ts @@ -229,71 +229,17 @@ describe('DonationItemsService', () => { expect(rice.detailsConfirmed).toEqual(true); }); - it('creates items with optional fields omitted', async () => { + it('sets detailsConfirmed to true since ozPerItem and estimatedValue are required', async () => { const donation = await getSeedDonation(); const transactionManager = testDataSource.createEntityManager(); - const minimalItems: CreateDonationItemDto[] = [ - { - itemName: 'Plain Item', - quantity: 3, - foodType: FoodType.DRIED_BEANS, - foodRescue: true, - }, - ]; - - const result = await service.createMultiple( - donation, - minimalItems, - transactionManager, - ); - - expect(result).toHaveLength(1); - expect(result[0].itemId).toBeDefined(); - expect(result[0].ozPerItem).toBeNull(); - expect(result[0].estimatedValue).toBeNull(); - expect(result[0].detailsConfirmed).toEqual(false); - }); - - it('sets detailsConfirmed to true only when both ozPerItem and estimatedValue are provided', async () => { - const donation = await getSeedDonation(); - const transactionManager = testDataSource.createEntityManager(); - - const mixedItems: CreateDonationItemDto[] = [ - { - itemName: 'Both Fields', - quantity: 4, - ozPerItem: 12, - estimatedValue: 3.5, - foodType: FoodType.DRIED_BEANS, - foodRescue: false, - }, - { - itemName: 'Missing Estimated Value', - quantity: 2, - ozPerItem: 8, - foodType: FoodType.DRIED_BEANS, - foodRescue: false, - }, - { - itemName: 'Missing Oz Per Item', - quantity: 6, - estimatedValue: 1.99, - foodType: FoodType.DRIED_BEANS, - foodRescue: false, - }, - ]; - const result = await service.createMultiple( donation, - mixedItems, + validItems, transactionManager, ); - const byName = Object.fromEntries(result.map((i) => [i.itemName, i])); - expect(byName['Both Fields'].detailsConfirmed).toEqual(true); - expect(byName['Missing Estimated Value'].detailsConfirmed).toEqual(false); - expect(byName['Missing Oz Per Item'].detailsConfirmed).toEqual(false); + expect(result.every((item) => item.detailsConfirmed)).toBe(true); }); it('rolls back all items when one fails within a transaction', async () => { @@ -309,6 +255,8 @@ describe('DonationItemsService', () => { { itemName: 'a'.repeat(1000), quantity: 5, + ozPerItem: 10, + estimatedValue: 2.5, foodType: FoodType.DRIED_BEANS, foodRescue: false, }, @@ -372,8 +320,8 @@ describe('DonationItemsService', () => { ): Promise { const result = await testDataSource.query( `INSERT INTO donation_items - (donation_id, item_name, quantity, reserved_quantity, food_type, details_confirmed) - VALUES ($1, 'Test Item', $2, $3, 'Granola', false) + (donation_id, item_name, quantity, reserved_quantity, oz_per_item, estimated_value, food_type, details_confirmed) + VALUES ($1, 'Test Item', $2, $3, 3.4, 3.4, 'Granola', false) RETURNING item_id`, [donationId, qty, reserved], ); @@ -494,51 +442,6 @@ describe('DonationItemsService', () => { .getRepository(DonationItem) .findOneBy({ itemId }); expect(item?.detailsConfirmed).toBe(false); - expect(item?.ozPerItem).toBeNull(); - }); - - it('returns false and does not confirm when only some fields are provided', async () => { - const donationId = await insertMatchedDonation(); - const itemId = await insertDonationItem(donationId, 10, 5); - - const result = await testDataSource.transaction((tm) => - service.updateItemDetails(donationId, [{ itemId, ozPerItem: 8.5 }], tm), - ); - - expect(result).toBe(false); - const item = await testDataSource - .getRepository(DonationItem) - .findOneBy({ itemId }); - expect(Number(item?.ozPerItem)).toBe(8.5); - expect(item?.estimatedValue).toBeNull(); - expect(item?.detailsConfirmed).toBe(false); - }); - - it('confirms item on a second call that supplies the remaining fields', async () => { - const donationId = await insertMatchedDonation(); - const itemId = await insertDonationItem(donationId, 10, 5); - - const firstResult = await testDataSource.transaction((tm) => - service.updateItemDetails(donationId, [{ itemId, ozPerItem: 8.5 }], tm), - ); - expect(firstResult).toBe(false); - - const secondResult = await testDataSource.transaction((tm) => - service.updateItemDetails( - donationId, - [{ itemId, estimatedValue: 12.0, foodRescue: true }], - tm, - ), - ); - expect(secondResult).toBe(true); - - const item = await testDataSource - .getRepository(DonationItem) - .findOneBy({ itemId }); - expect(Number(item?.ozPerItem)).toBe(8.5); - expect(Number(item?.estimatedValue)).toBe(12.0); - expect(item?.foodRescue).toBe(true); - expect(item?.detailsConfirmed).toBe(true); }); it('allows updating an already-confirmed item without throwing', async () => { @@ -552,7 +455,18 @@ describe('DonationItemsService', () => { ); const result = await testDataSource.transaction((tm) => - service.updateItemDetails(donationId, [{ itemId, ozPerItem: 9.0 }], tm), + service.updateItemDetails( + donationId, + [ + { + itemId, + ozPerItem: 9.0, + estimatedValue: 10.0, + foodRescue: true, + }, + ], + tm, + ), ); expect(result).toBe(true); diff --git a/apps/backend/src/donationItems/donationItems.service.ts b/apps/backend/src/donationItems/donationItems.service.ts index 8c8e778d4..311ee8a51 100644 --- a/apps/backend/src/donationItems/donationItems.service.ts +++ b/apps/backend/src/donationItems/donationItems.service.ts @@ -105,26 +105,15 @@ export class DonationItemsService { ); } - const updateData: Partial = {}; - if (dto.ozPerItem !== undefined) updateData.ozPerItem = dto.ozPerItem; - if (dto.estimatedValue !== undefined) - updateData.estimatedValue = dto.estimatedValue; - if (dto.foodRescue !== undefined) updateData.foodRescue = dto.foodRescue; - - // If included in DTO, keep it, otherwise use whatever is in the DB (could be null) - const resultingOzPerItem = - updateData.ozPerItem !== undefined - ? updateData.ozPerItem - : item.ozPerItem; - const resultingEstimatedValue = - updateData.estimatedValue !== undefined - ? updateData.estimatedValue - : item.estimatedValue; - - if (resultingOzPerItem != null && resultingEstimatedValue != null) { - updateData.detailsConfirmed = true; - confirmedDetailsForAnItem = true; - } + // ozPerItem, estimatedValue, and foodRescue are required on the DTO, so an + // update always supplies the full set of details and confirms the item. + const updateData: Partial = { + ozPerItem: dto.ozPerItem, + estimatedValue: dto.estimatedValue, + foodRescue: dto.foodRescue, + detailsConfirmed: true, + }; + confirmedDetailsForAnItem = true; await donationItemTransactionRepo.update(dto.itemId, updateData); } @@ -207,7 +196,7 @@ export class DonationItemsService { estimatedValue: item.estimatedValue, foodType: item.foodType, foodRescue: item.foodRescue, - detailsConfirmed: item.ozPerItem != null && item.estimatedValue != null, + detailsConfirmed: true, }), ); return transactionRepo.save(donationItems); diff --git a/apps/backend/src/donationItems/dtos/create-donation-items.dto.ts b/apps/backend/src/donationItems/dtos/create-donation-items.dto.ts index 3380ef7a6..6059732cd 100644 --- a/apps/backend/src/donationItems/dtos/create-donation-items.dto.ts +++ b/apps/backend/src/donationItems/dtos/create-donation-items.dto.ts @@ -5,7 +5,6 @@ import { IsEnum, IsNotEmpty, Length, - IsOptional, IsInt, IsBoolean, } from 'class-validator'; @@ -26,16 +25,14 @@ export class CreateDonationItemDto { { message: 'ozPerItem must have at most 2 decimal places' }, ) @Min(0.01) - @IsOptional() - ozPerItem?: number; + ozPerItem!: number; @IsNumber( { maxDecimalPlaces: 2 }, { message: 'estimatedValue must have at most 2 decimal places' }, ) @Min(0.01) - @IsOptional() - estimatedValue?: number; + estimatedValue!: number; @IsEnum(FoodType) foodType!: FoodType; diff --git a/apps/backend/src/donationItems/dtos/update-donation-item-details.dto.ts b/apps/backend/src/donationItems/dtos/update-donation-item-details.dto.ts index 7c2366761..83812ea93 100644 --- a/apps/backend/src/donationItems/dtos/update-donation-item-details.dto.ts +++ b/apps/backend/src/donationItems/dtos/update-donation-item-details.dto.ts @@ -1,27 +1,24 @@ -import { IsNumber, Min, IsBoolean, IsInt, IsOptional } from 'class-validator'; +import { IsNumber, Min, IsBoolean, IsInt } from 'class-validator'; export class UpdateDonationItemDetailsDto { @IsInt() @Min(1) itemId!: number; - @IsOptional() @IsNumber( { maxDecimalPlaces: 2 }, { message: 'Oz per item must have at most 2 decimal places' }, ) @Min(0.01, { message: 'Oz per item must be at least 0.01' }) - ozPerItem?: number; + ozPerItem!: number; - @IsOptional() @IsNumber( { maxDecimalPlaces: 2 }, { message: 'Estimated value must have at most 2 decimal places' }, ) @Min(0.01, { message: 'Estimated value must be at least 0.01' }) - estimatedValue?: number; + estimatedValue!: number; - @IsOptional() @IsBoolean() - foodRescue?: boolean; + foodRescue!: boolean; } diff --git a/apps/backend/src/donations/donations.controller.ts b/apps/backend/src/donations/donations.controller.ts index c98d5f031..3bd34c73f 100644 --- a/apps/backend/src/donations/donations.controller.ts +++ b/apps/backend/src/donations/donations.controller.ts @@ -102,8 +102,8 @@ export class DonationsController { properties: { itemName: { type: 'string', example: 'Canned Beans' }, quantity: { type: 'integer', example: 1 }, - ozPerItem: { type: 'number', example: 0.01, nullable: true }, - estimatedValue: { type: 'number', example: 0.01, nullable: true }, + ozPerItem: { type: 'number', example: 0.01 }, + estimatedValue: { type: 'number', example: 0.01 }, foodType: { type: 'enum', enum: Object.values(FoodType), diff --git a/apps/backend/src/donations/donations.service.spec.ts b/apps/backend/src/donations/donations.service.spec.ts index bcdd0f9ec..76b8e16fd 100644 --- a/apps/backend/src/donations/donations.service.spec.ts +++ b/apps/backend/src/donations/donations.service.spec.ts @@ -71,8 +71,8 @@ async function insertDonationItem( ): Promise { const result = await testDataSource.query( `INSERT INTO donation_items - (donation_id, item_name, quantity, reserved_quantity, food_type, details_confirmed) - VALUES ($1, 'Test Item', $2, $3, 'Granola', false) + (donation_id, item_name, quantity, reserved_quantity, oz_per_item, estimated_value, food_type, details_confirmed) + VALUES ($1, 'Test Item', $2, $3, 3.4, 3.4, 'Granola', false) RETURNING item_id`, [donationId, qty, reserved], ); @@ -1256,6 +1256,8 @@ describe('DonationService', () => { quantity: 5, foodType: FoodType.DAIRY_FREE_ALTERNATIVES, foodRescue: false, + ozPerItem: 3.4, + estimatedValue: 3.4, }, ], }, @@ -1398,21 +1400,6 @@ describe('DonationService', () => { expect(spy).toHaveBeenCalled(); }); - - it('does not call checkAndFulfillDonation when no items are fully confirmed', async () => { - const donationId = await insertMatchedDonation(); - const itemId = await insertDonationItem(donationId, 10, 5); - - const spy = jest.spyOn(service, 'checkAndFulfillDonation'); - - await service.updateDonationItemDetails(donationId, [ - { itemId, ozPerItem: 5.0 }, - ]); - - const dbDonation = await service.findOne(donationId); - expect(dbDonation.status).toBe(DonationStatus.MATCHED); - expect(spy).not.toHaveBeenCalled(); - }); }); describe('checkAndFulfillDonation', () => { @@ -1423,8 +1410,8 @@ describe('DonationService', () => { ): Promise { const result = await testDataSource.query( `INSERT INTO donation_items - (donation_id, item_name, quantity, reserved_quantity, food_type, details_confirmed) - VALUES ($1, 'Test Item', $2, $3, 'Granola', true) + (donation_id, item_name, quantity, reserved_quantity, oz_per_item, estimated_value, food_type, details_confirmed) + VALUES ($1, 'Test Item', $2, $3, 3.4, 3.4, 'Granola', true) RETURNING item_id`, [donationId, qty, reserved], ); diff --git a/apps/backend/src/foodManufacturers/dtos/donation-details-dto.ts b/apps/backend/src/foodManufacturers/dtos/donation-details-dto.ts index 5a8403bff..0b11f304e 100644 --- a/apps/backend/src/foodManufacturers/dtos/donation-details-dto.ts +++ b/apps/backend/src/foodManufacturers/dtos/donation-details-dto.ts @@ -6,8 +6,8 @@ export class DonationItemWithAllocatedQuantityDto { itemName!: string; foodType!: FoodType; allocatedQuantity!: number; - ozPerItem?: number; - estimatedValue?: number; + ozPerItem!: number; + estimatedValue!: number; foodRescue!: boolean; } diff --git a/apps/backend/src/foodManufacturers/manufacturers.controller.spec.ts b/apps/backend/src/foodManufacturers/manufacturers.controller.spec.ts index ac7d46fa5..0e3878c9c 100644 --- a/apps/backend/src/foodManufacturers/manufacturers.controller.spec.ts +++ b/apps/backend/src/foodManufacturers/manufacturers.controller.spec.ts @@ -123,6 +123,8 @@ describe('FoodManufacturersController', () => { foodType: FoodType.DAIRY_FREE_ALTERNATIVES, allocatedQuantity: 10, foodRescue: false, + estimatedValue: 3.4, + ozPerItem: 3.4, }, ], }, diff --git a/apps/backend/src/foodManufacturers/manufacturers.service.ts b/apps/backend/src/foodManufacturers/manufacturers.service.ts index 25e591cd0..09675016a 100644 --- a/apps/backend/src/foodManufacturers/manufacturers.service.ts +++ b/apps/backend/src/foodManufacturers/manufacturers.service.ts @@ -119,8 +119,8 @@ export class FoodManufacturersService { (sum, a) => sum + a.allocatedQuantity, 0, ), - ozPerItem: item.ozPerItem ?? undefined, - estimatedValue: item.estimatedValue ?? undefined, + ozPerItem: item.ozPerItem, + estimatedValue: item.estimatedValue, foodRescue: item.foodRescue, }); diff --git a/apps/backend/src/migrations/1782000000000-MakeDonationItemDetailsRequired.ts b/apps/backend/src/migrations/1782000000000-MakeDonationItemDetailsRequired.ts new file mode 100644 index 000000000..ab60bb698 --- /dev/null +++ b/apps/backend/src/migrations/1782000000000-MakeDonationItemDetailsRequired.ts @@ -0,0 +1,31 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class MakeDonationItemDetailsRequired1782000000000 + implements MigrationInterface +{ + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + UPDATE donation_items + SET oz_per_item = 0 + WHERE oz_per_item IS NULL + `); + await queryRunner.query(` + UPDATE donation_items + SET estimated_value = 0 + WHERE estimated_value IS NULL + `); + await queryRunner.query(` + ALTER TABLE donation_items + ALTER COLUMN oz_per_item SET NOT NULL, + ALTER COLUMN estimated_value SET NOT NULL + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE donation_items + ALTER COLUMN oz_per_item DROP NOT NULL, + ALTER COLUMN estimated_value DROP NOT NULL + `); + } +} diff --git a/apps/backend/src/orders/order.service.spec.ts b/apps/backend/src/orders/order.service.spec.ts index 3d32f52a5..0a8198e90 100644 --- a/apps/backend/src/orders/order.service.spec.ts +++ b/apps/backend/src/orders/order.service.spec.ts @@ -1331,8 +1331,8 @@ ${request.pantry.shipmentAddressCity}, ${request.pantry.shipmentAddressState} ${ async function insertDonationItem(donationId: number): Promise { const [{ item_id }] = await testDataSource.query( - `INSERT INTO donation_items (donation_id, item_name, quantity, reserved_quantity, food_type, food_rescue, details_confirmed) - VALUES ($1, 'Test Item', 10, 10, 'Granola', false, false) + `INSERT INTO donation_items (donation_id, item_name, quantity, reserved_quantity, oz_per_item, estimated_value, food_type, food_rescue, details_confirmed) + VALUES ($1, 'Test Item', 10, 10, 3.4, 3.4, 'Granola', false, false) RETURNING item_id`, [donationId], ); diff --git a/apps/backend/src/users/users.service.spec.ts b/apps/backend/src/users/users.service.spec.ts index 03c76ca57..ace8a47f4 100644 --- a/apps/backend/src/users/users.service.spec.ts +++ b/apps/backend/src/users/users.service.spec.ts @@ -439,6 +439,8 @@ describe('UsersService', () => { itemName: 'Test Item', quantity: 10, foodType: FoodType.GRANOLA, + ozPerItem: 3.4, + estimatedValue: 3.4, foodRescue: false, }, ], diff --git a/apps/frontend/src/components/forms/fmCompleteRequiredActionsModal.tsx b/apps/frontend/src/components/forms/fmCompleteRequiredActionsModal.tsx index 980c62d01..092d4f7b4 100644 --- a/apps/frontend/src/components/forms/fmCompleteRequiredActionsModal.tsx +++ b/apps/frontend/src/components/forms/fmCompleteRequiredActionsModal.tsx @@ -150,8 +150,8 @@ const FmCompleteRequiredActionsModal: React.FC< donation.relevantDonationItems.map((item) => [ item.itemId, { - ozPerItem: item.ozPerItem?.toString() ?? '', - estimatedValue: item.estimatedValue?.toString() ?? '', + ozPerItem: item.ozPerItem.toString(), + estimatedValue: item.estimatedValue.toString(), foodRescue: item.foodRescue, }, ]), @@ -167,8 +167,8 @@ const FmCompleteRequiredActionsModal: React.FC< donation.relevantDonationItems.length > 0 && donation.relevantDonationItems.every( (item) => - (itemFormData[item.itemId]?.ozPerItem ?? '') !== '' && - (itemFormData[item.itemId]?.estimatedValue ?? '') !== '', + itemFormData[item.itemId].ozPerItem !== '' && + itemFormData[item.itemId].estimatedValue !== '', ), [itemFormData], ); @@ -228,9 +228,8 @@ const FmCompleteRequiredActionsModal: React.FC< .filter((item) => { const formData = itemFormData[item.itemId]; return ( - formData.ozPerItem !== (item.ozPerItem?.toString() ?? '') || - formData.estimatedValue !== - (item.estimatedValue?.toString() ?? '') || + formData.ozPerItem !== item.ozPerItem.toString() || + formData.estimatedValue !== item.estimatedValue.toString() || formData.foodRescue !== item.foodRescue ); }) @@ -238,12 +237,10 @@ const FmCompleteRequiredActionsModal: React.FC< const formData = itemFormData[item.itemId]; const dto: UpdateDonationItemDetailsDto = { itemId: item.itemId, + ozPerItem: parseFloat(formData.ozPerItem), + estimatedValue: parseFloat(formData.estimatedValue), foodRescue: formData.foodRescue, }; - if (formData.ozPerItem !== '') - dto.ozPerItem = parseFloat(formData.ozPerItem); - if (formData.estimatedValue !== '') - dto.estimatedValue = parseFloat(formData.estimatedValue); return dto; }); @@ -502,8 +499,12 @@ const FmCompleteRequiredActionsModal: React.FC< {stage === 'itemDetails' && ( <> - Please fill out the missing fields information to record - donation details. + Please confirm the following information to record donation + details. + + + Please do not include shipping/delivery costs in Food Donation + Value. @@ -514,15 +515,22 @@ const FmCompleteRequiredActionsModal: React.FC< > - + Food Item - + Oz. per item + + * + - - Donation Value + + Donation Value (Fair Market Value of Food Only) + + * + + = ({ items: rows.map((row) => ({ itemName: row.foodItem, quantity: parseInt(row.numItems), - ozPerItem: row.ozPerItem ? parseFloat(row.ozPerItem) : undefined, - estimatedValue: row.valuePerItem - ? parseFloat(row.valuePerItem) - : undefined, + ozPerItem: parseFloat(row.ozPerItem), + estimatedValue: parseFloat(row.valuePerItem), foodType: row.foodType as FoodType, foodRescue: row.foodRescue, })), @@ -298,10 +302,14 @@ const NewDonationFormModal: React.FC = ({ - + Please fill out the following information to record donation details. + + Please do not include shipping/delivery costs in Food Donation + Value. + = ({ Oz. per item + + * + - Donation Value + Donation Value + (Fair Market Value of Food Only) + + * + = ({ lineHeight="tight" > Food Rescue + + * + diff --git a/apps/frontend/src/components/forms/resubmitDonationModal.tsx b/apps/frontend/src/components/forms/resubmitDonationModal.tsx index dd75ac18d..dbd716631 100644 --- a/apps/frontend/src/components/forms/resubmitDonationModal.tsx +++ b/apps/frontend/src/components/forms/resubmitDonationModal.tsx @@ -116,12 +116,8 @@ const ResubmitDonationModal: React.FC = ({ items: items.map((item) => ({ itemName: item.itemName, quantity: item.quantity, - ozPerItem: - item.ozPerItem != null ? Number(item.ozPerItem) : undefined, - estimatedValue: - item.estimatedValue != null - ? Number(item.estimatedValue) - : undefined, + ozPerItem: Number(item.ozPerItem), + estimatedValue: Number(item.estimatedValue), foodType: item.foodType, foodRescue: item.foodRescue, })), diff --git a/apps/frontend/src/types/types.ts b/apps/frontend/src/types/types.ts index adf226ceb..4910e1521 100644 --- a/apps/frontend/src/types/types.ts +++ b/apps/frontend/src/types/types.ts @@ -211,8 +211,8 @@ export interface DonationItemWithAllocatedQuantity { foodType: FoodType; allocatedQuantity: number; detailsConfirmed: boolean; - ozPerItem?: number; - estimatedValue?: number; + ozPerItem: number; + estimatedValue: number; foodRescue: boolean; } @@ -236,8 +236,8 @@ export interface DonationItem { itemName: string; quantity: number; reservedQuantity: number; - ozPerItem?: number; - estimatedValue?: number; + ozPerItem: number; + estimatedValue: number; foodType: FoodType; foodRescue: boolean; } @@ -482,8 +482,8 @@ export interface CreateDonationDto { export interface CreateDonationItemDto { itemName: string; quantity: number; - ozPerItem?: number; - estimatedValue?: number; + ozPerItem: number; + estimatedValue: number; foodType: FoodType; foodRescue: boolean; } @@ -607,9 +607,9 @@ export interface BulkUpdateTrackingCostDto { export interface UpdateDonationItemDetailsDto { itemId: number; - ozPerItem?: number; - estimatedValue?: number; - foodRescue?: boolean; + ozPerItem: number; + estimatedValue: number; + foodRescue: boolean; } export enum AlertStatus {