Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 60 additions & 2 deletions src/modules/inventory/inventory.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,38 @@ export class InventoryController {
const item = await this.itemRepo.findOne(dto.itemId).exec();
if (!item) throw new BadRequestException("Item not found");

// Validate current location/organizer matches 'from' fields if provided
if (
dto.fromLocationId !== undefined &&
item.holderLocationId !== dto.fromLocationId
) {
throw new BadRequestException(
`Item is not at the specified 'from' location. Current location: ${item.holderLocationId}, Expected: ${dto.fromLocationId}`,
);
}

if (
dto.fromOrganizerId !== undefined &&
item.holderOrganizerId !== dto.fromOrganizerId
) {
throw new BadRequestException(
`Item is not with the specified 'from' organizer. Current organizer: ${item.holderOrganizerId}, Expected: ${dto.fromOrganizerId}`,
);
}

// Validate business rules for specific movements
if (dto.reason === "return" && item.status !== "checked_out") {
throw new BadRequestException(
"Cannot return an item that is not checked out",
);
}

if (dto.reason === "checkout" && item.status !== "active") {
throw new BadRequestException(
"Cannot checkout an item that is not active",
);
}

const now = Date.now();

// Create movement
Expand All @@ -225,26 +257,52 @@ export class InventoryController {
...dto,
};

// Update item holder + status smartly
// Update item holder + status with comprehensive logic
item.holderLocationId = dto.toLocationId ?? null;
item.holderOrganizerId = dto.toOrganizerId ?? null;
item.updatedAt = now;

switch (dto.reason) {
case "lost":
item.status = "lost";
// Clear holder information for lost items
item.holderLocationId = null;
item.holderOrganizerId = null;
break;
case "disposed":
item.status = "disposed";
// Clear holder information for disposed items
item.holderLocationId = null;
item.holderOrganizerId = null;
break;
case "checkout":
item.status = "checked_out";
break;
case "return":
item.status = "active";
break;
case "repair":
// Item under repair remains active but location/organizer is updated
// Status stays the same unless it was previously lost/disposed
if (item.status === "lost" || item.status === "disposed") {
item.status = "active";
}
break;
case "transfer":
// Transfer keeps current status unless item was lost/disposed
if (item.status === "lost" || item.status === "disposed") {
item.status = "active";
}
break;
case "other":
// For 'other' movements, status logic depends on context
// Keep current status unless explicitly moving from lost/disposed
if (item.status === "lost" || item.status === "disposed") {
item.status = "active";
}
break;
default:
// keep current status
// Keep current status for any other reasons
break;
}

Expand Down