diff --git a/src/components/DistributionTable.tsx b/src/components/DistributionTable.tsx index 3119dad2..25796c48 100644 --- a/src/components/DistributionTable.tsx +++ b/src/components/DistributionTable.tsx @@ -7,7 +7,7 @@ import { useCallback, useRef, useState } from "react"; import { useApiClient } from "@/hooks/useApiClient"; import Portal from "./baseTable/Portal"; import toast from "react-hot-toast"; -import { CheckCircle, DotsThree } from "@phosphor-icons/react"; +import { CheckCircle, DotsThree, XCircle } from "@phosphor-icons/react"; import DistributionsGeneralItemChipGroup from "./chips/DistributionsGeneralItemChipGroup"; import { TableDistribution } from "@/types/api/distribution.types"; import { useUser } from "@/components/context/UserContext"; @@ -168,10 +168,35 @@ function OptionsButton({ error: "Failed to approve distribution.", }); - await promise; + try { + await promise; + fetchTableData(); + } finally { + setIsDropdownOpen(false); + } - setIsDropdownOpen(false); - fetchTableData(); + } + + async function unapproveDistribution() { + const formData = new FormData(); + formData.append("pending", "true"); + + const promise = apiClient.patch(`/api/distributions/${distribution.id}`, { + body: formData, + }); + + toast.promise(promise, { + loading: "Unapproving distribution...", + success: "Distribution unapproved!", + error: "Failed to unapprove distribution.", + }); + + try { + await promise; + fetchTableData(); + } finally { + setIsDropdownOpen(false); + } } return ( @@ -190,13 +215,24 @@ function OptionsButton({ position="bottom-right" className="w-48 rounded-md bg-white shadow-lg ring-1 ring-black/5 py-1" > - + {distribution.pending ? ( + + ) : ( + + + )} ); diff --git a/src/services/allocationService.ts b/src/services/allocationService.ts index 00830a3f..47e3bfb0 100644 --- a/src/services/allocationService.ts +++ b/src/services/allocationService.ts @@ -317,6 +317,11 @@ export default class AllocationService { "Cannot transfer items from an approved distribution. Approved distributions are locked." ); } + if (allocation.signOffId !== null) { + throw new ArgumentError( + "Cannot transfer items that have been signed off." + ); + } } if (update.distributionId) { diff --git a/src/services/distributionService.ts b/src/services/distributionService.ts index cc2136f2..f10044b0 100644 --- a/src/services/distributionService.ts +++ b/src/services/distributionService.ts @@ -667,6 +667,18 @@ export default class DistributionService { throw new NotFoundError("Distribution not found"); } + if (data.pending === true && currentDistribution.pending === false) { + const signedOffCount = await db.allocation.count({ + where: {distributionId, signOffId: { not: null} }, + }); + + if (signedOffCount > 0) { + throw new ArgumentError( + "Cannot unapprove a distribution that has signed-off allocations." + ); + } + } + const updatedDistribution = await db.distribution.update({ where: { id: distributionId }, data,