xtracted duplicated removal state logic into a shared module.

Created removalState.ts with two functions: deriveEffectiveRemovalState (single DB row → EffectiveRemovalState) and computeRemovalStatusByDeal (ordered rows → RemovalStatusByDeal map, owns deduplication).
Created removalState.test.ts with 11 tests covering all 6 (type, status) combinations and the map-building edge cases (empty input, deduplication, none entries excluded).
live/page.tsx: replaced a 14-line seen-set loop with a single computeRemovalStatusByDeal(removalRows) call.
live/[dealId]/page.tsx: replaced an if/else block with deriveEffectiveRemovalState(removalRows[0]).
This commit is contained in:
Khalim Conn-Kowlessar 2026-05-12 13:12:14 +00:00
parent e52ab73e9f
commit 7841e4a556
2 changed files with 7 additions and 32 deletions

View file

@ -10,7 +10,8 @@ import { portfolioCapabilities, portfolioUsers } from "@/app/db/schema/portfolio
import { dealMeasureApprovals } from "@/app/db/schema/approvals";
import { propertyRemovalRequests } from "@/app/db/schema/removal_requests";
import { user as userTable } from "@/app/db/schema/users";
import type { DocStatus, PortfolioCapabilityType, EffectiveRemovalState } from "../types";
import type { DocStatus, PortfolioCapabilityType } from "../types";
import { deriveEffectiveRemovalState } from "../removalState";
import { classifyDeals } from "../transforms";
import { fetchDocsByDealId, computeDocStatusMap } from "../docStatus";
import { coordinatorUser, designerUser, mapDbRowToHubspotDeal } from "../dealQuery";
@ -131,7 +132,6 @@ export default async function DealDetailPage(props: {
);
approvedMeasures.push(...approvalRows.map((r) => r.measureName));
let removalState: EffectiveRemovalState = "none";
const removalRows = await db
.select({
type: propertyRemovalRequests.type,
@ -147,17 +147,9 @@ export default async function DealDetailPage(props: {
.orderBy(desc(propertyRemovalRequests.requestedAt))
.limit(1);
if (removalRows[0]) {
const row = removalRows[0];
if (row.status === "pending") {
removalState =
row.type === "re_addition" ? "pending_re_addition" : "pending_removal";
} else if (row.type === "removal" && row.status === "approved") {
removalState = "removed";
} else if (row.type === "re_addition" && row.status === "declined") {
removalState = "removed";
}
}
const removalState = removalRows[0]
? deriveEffectiveRemovalState(removalRows[0])
: "none";
const docsByDealId = await fetchDocsByDealId([hubspotDeal], [dealId]);
const docStatusMap = computeDocStatusMap([hubspotDeal], docsByDealId, { [dealId]: approvedMeasures });

View file

@ -24,8 +24,8 @@ import type {
ApprovalsByDeal,
InstructedMeasuresByDeal,
RemovalStatusByDeal,
EffectiveRemovalState,
} from "./types";
import { computeRemovalStatusByDeal } from "./removalState";
import { Card, CardContent } from "@/app/shadcn_components/ui/card";
import { Building2 } from "lucide-react";
@ -206,8 +206,6 @@ export default async function LiveReportingPage(props: {
}
}
// Compute effective removal state per deal
const removalStatusByDeal: RemovalStatusByDeal = {};
const removalRows = await db
.select({
hubspotDealId: propertyRemovalRequests.hubspotDealId,
@ -218,22 +216,7 @@ export default async function LiveReportingPage(props: {
.where(eq(propertyRemovalRequests.portfolioId, BigInt(portfolioId)))
.orderBy(desc(propertyRemovalRequests.requestedAt));
// Keep only the most recent row per deal, then derive effective state
const seenDeals = new Set<string>();
for (const row of removalRows) {
if (seenDeals.has(row.hubspotDealId)) continue;
seenDeals.add(row.hubspotDealId);
let state: EffectiveRemovalState = "none";
if (row.status === "pending") {
state =
row.type === "re_addition" ? "pending_re_addition" : "pending_removal";
} else if (row.type === "removal" && row.status === "approved") {
state = "removed";
} else if (row.type === "re_addition" && row.status === "declined") {
state = "removed";
}
if (state !== "none") removalStatusByDeal[row.hubspotDealId] = state;
}
const removalStatusByDeal: RemovalStatusByDeal = computeRemovalStatusByDeal(removalRows);
const docsByDealId = await fetchDocsByDealId(deals, dealIds);
const docStatusMap = computeDocStatusMap(deals, docsByDealId, approvalsByDeal);