item master cleanup

This commit is contained in:
2026-03-15 21:32:45 -05:00
parent 8029b308e9
commit f2b820746a
3 changed files with 48 additions and 3 deletions

View File

@@ -109,7 +109,7 @@ export function InventoryListPage() {
<th className="px-2 py-2">Type</th>
<th className="px-2 py-2">Status</th>
<th className="px-2 py-2">UOM</th>
<th className="px-2 py-2">Flags</th>
<th className="px-2 py-2">Qty</th>
<th className="px-2 py-2">BOM</th>
<th className="px-2 py-2">Updated</th>
</tr>
@@ -131,8 +131,8 @@ export function InventoryListPage() {
</td>
<td className="px-2 py-2 text-muted">{item.unitOfMeasure}</td>
<td className="px-2 py-2 text-xs text-muted">
<div>{item.isSellable ? "Sellable" : "Not sellable"}</div>
<div>{item.isPurchasable ? "Purchasable" : "Not purchasable"}</div>
<div>Total {item.onHandQuantity}</div>
<div>Available {item.availableQuantity}</div>
</td>
<td className="px-2 py-2 text-muted">{item.bomLineCount} lines</td>
<td className="px-2 py-2 text-muted">{new Date(item.updatedAt).toLocaleDateString()}</td>

View File

@@ -341,6 +341,23 @@ function buildStockBalances(transactions: InventoryTransactionRecord[], reservat
);
}
function calculateSummaryQuantities(
transactions: Array<{ transactionType: string; quantity: number }>,
reservations: Array<{ status: string; quantity: number }>
) {
const onHandQuantity = transactions.reduce((sum, transaction) => {
return sum + getSignedQuantity(transaction.transactionType as InventoryTransactionType, transaction.quantity);
}, 0);
const reservedQuantity = reservations.reduce((sum, reservation) => {
return reservation.status === "ACTIVE" ? sum + reservation.quantity : sum;
}, 0);
return {
onHandQuantity,
availableQuantity: onHandQuantity - reservedQuantity,
};
}
function mapSummary(record: {
id: string;
sku: string;
@@ -351,8 +368,12 @@ function mapSummary(record: {
isSellable: boolean;
isPurchasable: boolean;
updatedAt: Date;
inventoryTransactions?: Array<{ transactionType: string; quantity: number }>;
reservations?: Array<{ status: string; quantity: number }>;
_count: { bomLines: number };
}): InventoryItemSummaryDto {
const quantities = calculateSummaryQuantities(record.inventoryTransactions ?? [], record.reservations ?? []);
return {
id: record.id,
sku: record.sku,
@@ -362,6 +383,8 @@ function mapSummary(record: {
unitOfMeasure: record.unitOfMeasure as InventoryUnitOfMeasure,
isSellable: record.isSellable,
isPurchasable: record.isPurchasable,
onHandQuantity: quantities.onHandQuantity,
availableQuantity: quantities.availableQuantity,
bomLineCount: record._count.bomLines,
updatedAt: record.updatedAt.toISOString(),
};
@@ -391,6 +414,14 @@ function mapDetail(record: InventoryDetailRecord): InventoryItemDetailDto {
isSellable: record.isSellable,
isPurchasable: record.isPurchasable,
updatedAt: record.updatedAt,
inventoryTransactions: record.inventoryTransactions.map((transaction) => ({
transactionType: transaction.transactionType,
quantity: transaction.quantity,
})),
reservations: record.reservations.map((reservation) => ({
status: reservation.status,
quantity: reservation.quantity,
})),
_count: { bomLines: record.bomLines.length },
}),
description: record.description,
@@ -645,6 +676,18 @@ export async function listInventoryItems(filters: InventoryListFilters = {}) {
const items = await prisma.inventoryItem.findMany({
where: buildWhereClause(filters),
include: {
inventoryTransactions: {
select: {
transactionType: true,
quantity: true,
},
},
reservations: {
select: {
status: true,
quantity: true,
},
},
_count: {
select: {
bomLines: true,

View File

@@ -114,6 +114,8 @@ export interface InventoryItemSummaryDto {
unitOfMeasure: InventoryUnitOfMeasure;
isSellable: boolean;
isPurchasable: boolean;
onHandQuantity: number;
availableQuantity: number;
bomLineCount: number;
updatedAt: string;
}