This commit is contained in:
2026-03-15 14:11:21 -05:00
parent 1fcb0c5480
commit 857d34397e
28 changed files with 848 additions and 45 deletions

View File

@@ -25,6 +25,7 @@ import type {
InventoryUnitOfMeasure,
} from "@mrp/shared/dist/inventory/types.js";
import { logAuditEvent } from "../../lib/audit.js";
import { prisma } from "../../lib/prisma.js";
type BomLineRecord = {
@@ -841,6 +842,21 @@ export async function createInventoryTransaction(itemId: string, payload: Invent
},
});
await logAuditEvent({
actorId: createdById,
entityType: "inventory-item",
entityId: itemId,
action: "transaction.created",
summary: `Posted ${payload.transactionType.toLowerCase()} transaction for inventory item ${itemId}.`,
metadata: {
transactionType: payload.transactionType,
quantity: payload.quantity,
warehouseId: payload.warehouseId,
locationId: payload.locationId,
reference: payload.reference.trim(),
},
});
const nextDetail = await getInventoryItemById(itemId);
return nextDetail ? { ok: true as const, item: nextDetail } : { ok: false as const, reason: "Unable to load updated inventory item." };
}
@@ -921,11 +937,26 @@ export async function createInventoryTransfer(itemId: string, payload: Inventory
});
});
await logAuditEvent({
actorId: createdById,
entityType: "inventory-item",
entityId: itemId,
action: "transfer.created",
summary: `Transferred ${payload.quantity} units for inventory item ${itemId}.`,
metadata: {
quantity: payload.quantity,
fromWarehouseId: payload.fromWarehouseId,
fromLocationId: payload.fromLocationId,
toWarehouseId: payload.toWarehouseId,
toLocationId: payload.toLocationId,
},
});
const nextDetail = await getInventoryItemById(itemId);
return nextDetail ? { ok: true as const, item: nextDetail } : { ok: false as const, reason: "Unable to load updated inventory item." };
}
export async function createInventoryReservation(itemId: string, payload: InventoryReservationInput) {
export async function createInventoryReservation(itemId: string, payload: InventoryReservationInput, createdById?: string | null) {
const item = await prisma.inventoryItem.findUnique({
where: { id: itemId },
select: { id: true },
@@ -969,11 +1000,25 @@ export async function createInventoryReservation(itemId: string, payload: Invent
},
});
await logAuditEvent({
actorId: createdById,
entityType: "inventory-item",
entityId: itemId,
action: "reservation.created",
summary: `Created manual reservation for inventory item ${itemId}.`,
metadata: {
quantity: payload.quantity,
warehouseId: payload.warehouseId,
locationId: payload.locationId,
sourceType: "MANUAL",
},
});
const nextDetail = await getInventoryItemById(itemId);
return nextDetail ? { ok: true as const, item: nextDetail } : { ok: false as const, reason: "Unable to load updated inventory item." };
}
export async function createInventoryItem(payload: InventoryItemInput) {
export async function createInventoryItem(payload: InventoryItemInput, actorId?: string | null) {
const validatedBom = await validateBomLines(null, payload.bomLines);
if (!validatedBom.ok) {
return null;
@@ -1012,10 +1057,24 @@ export async function createInventoryItem(payload: InventoryItemInput) {
},
});
await logAuditEvent({
actorId,
entityType: "inventory-item",
entityId: item.id,
action: "created",
summary: `Created inventory item ${payload.sku}.`,
metadata: {
sku: payload.sku,
name: payload.name,
type: payload.type,
status: payload.status,
},
});
return getInventoryItemById(item.id);
}
export async function updateInventoryItem(itemId: string, payload: InventoryItemInput) {
export async function updateInventoryItem(itemId: string, payload: InventoryItemInput, actorId?: string | null) {
const existingItem = await prisma.inventoryItem.findUnique({
where: { id: itemId },
});
@@ -1061,6 +1120,20 @@ export async function updateInventoryItem(itemId: string, payload: InventoryItem
},
});
await logAuditEvent({
actorId,
entityType: "inventory-item",
entityId: item.id,
action: "updated",
summary: `Updated inventory item ${payload.sku}.`,
metadata: {
sku: payload.sku,
name: payload.name,
type: payload.type,
status: payload.status,
},
});
return getInventoryItemById(item.id);
}
@@ -1092,7 +1165,7 @@ export async function getWarehouseById(warehouseId: string) {
return warehouse ? mapWarehouseDetail(warehouse) : null;
}
export async function createWarehouse(payload: WarehouseInput) {
export async function createWarehouse(payload: WarehouseInput, actorId?: string | null) {
const locations = normalizeWarehouseLocations(payload.locations);
const warehouse = await prisma.warehouse.create({
@@ -1113,10 +1186,23 @@ export async function createWarehouse(payload: WarehouseInput) {
},
});
await logAuditEvent({
actorId,
entityType: "warehouse",
entityId: warehouse.id,
action: "created",
summary: `Created warehouse ${warehouse.code}.`,
metadata: {
code: warehouse.code,
name: warehouse.name,
locationCount: warehouse.locations.length,
},
});
return mapWarehouseDetail(warehouse);
}
export async function updateWarehouse(warehouseId: string, payload: WarehouseInput) {
export async function updateWarehouse(warehouseId: string, payload: WarehouseInput, actorId?: string | null) {
const existingWarehouse = await prisma.warehouse.findUnique({
where: { id: warehouseId },
});
@@ -1145,5 +1231,18 @@ export async function updateWarehouse(warehouseId: string, payload: WarehouseInp
},
});
await logAuditEvent({
actorId,
entityType: "warehouse",
entityId: warehouse.id,
action: "updated",
summary: `Updated warehouse ${warehouse.code}.`,
metadata: {
code: warehouse.code,
name: warehouse.name,
locationCount: warehouse.locations.length,
},
});
return mapWarehouseDetail(warehouse);
}