import { db } from "@/database/db";
import { tool, userTool } from "@/database/schema";
import { dbGetAll } from "@/lib/db/drizzle-client";
import { UserId } from "@/server/user/domain/models";
import { and, asc, eq, inArray, sql } from "drizzle-orm";
import { DeleteTool, Tool, UserTool, UserToolQuery } from "../domain/models";
import { createLogRecord } from "@/server/log";
import { ToolRepository } from "../domain/repositories";
import { DeleteUserToolDto } from "../application/dto";
class ToolRepositoryImpl implements ToolRepository {
async getAll(): Promise<Tool[]> {
return dbGetAll("tool", {
with: {
userTool: {
with: {
user: true,
},
},
},
orderBy: [asc(tool.id)],
});
}
async create(data: Tool, userId: UserId): Promise<Tool> {
await db.transaction(async (tx) => {
const createPromise = tx.insert(tool).values(data).returning();
const logRecordPromise = createLogRecord(tx, {
userId: userId.value,
modifiedItem: `Herramienta-${data.name}`,
eventType: "crear",
tableName: "tool",
item: data,
});
await Promise.all([createPromise, logRecordPromise]);
});
return data;
}
async delete(input: DeleteTool, userId: UserId): Promise<Tool[]> {
return await db.transaction(async (tx) => {
const deletedTools = await tx
.delete(tool)
.where(inArray(tool.id, input.toolIds))
.returning();
const logRecordPromises = deletedTools.map((item) =>
createLogRecord(tx, {
userId: userId.value,
modifiedItem: `Material-${item.name}`,
eventType: "eliminar",
tableName: "materials",
item: item,
})
);
await Promise.all([...logRecordPromises]);
return deletedTools;
});
}
async getUserTools(userId: UserId): Promise<UserToolQuery[]> {
const data = await db
.select({
id: tool.id,
name: tool.name,
inStock: tool.quantity,
assigned: userTool.quantity,
totalAssignedUsers: sql`SUM(COALESCE(${userTool.quantity}, 0))`,
})
.from(tool)
.innerJoin(
userTool,
and(eq(tool.id, userTool.toolId), eq(userTool.userId, userId.value))
)
.groupBy(tool.id, userTool.quantity);
return data as UserToolQuery[];
}
async assignUserTools(data: UserTool[]): Promise<UserTool[]> {
await db.transaction(async (tx) => {
const assignToolPromises = data.map((item) =>
tx
.insert(userTool)
.values({ id: item.id!, ...item })
.onConflictDoUpdate({
target: [userTool.userId, userTool.toolId],
set: { quantity: sql`${userTool.quantity} + ${item.quantity}` },
})
);
const logRecordPromises = data.map((item) =>
createLogRecord(tx, {
userId: item.userId,
modifiedItem: `Tool-${item.toolName}-asignada`,
eventType: "crear",
tableName: "userTool",
item: item,
})
);
await Promise.all([...assignToolPromises, ...logRecordPromises]);
});
return data;
}
async deleteUserTools(data: DeleteUserToolDto[]):Promise<any[]>{
await db.transaction(async(tx)=>{
const deleleUserTools = data?.map(({ toolId, userId }) => {
return tx
.delete(userTool)
.where(
and(eq(userTool.userId, userId), eq(userTool.toolId, toolId))
);
});
const logRecordPromises = data.map((item) =>
createLogRecord(tx, {
userId: item?.userId!,
modifiedItem: `Tool-${item?.toolName}-eliminada`,
eventType: 'eliminar',
tableName: "userTool",
item: item!,
})
);
await Promise.all([...deleleUserTools,...logRecordPromises])
})
return data
}
async updateAssignUserTools(data: UserTool[]): Promise<UserTool[]> {
await db.transaction(async (tx) => {
const updateAssignToolPromises = data.map((item) =>
tx
.update(userTool)
.set({ quantity: item?.quantity })
.where(
and(
eq(userTool.toolId, item?.toolId),
eq(userTool.userId, item.userId)
)
)
);
const logRecordPromises = data.map((item) =>
createLogRecord(tx, {
userId: item?.userId!,
modifiedItem: `Tool-${item?.toolName}-actualizada`,
eventType: 'modificar',
tableName: "userTool",
item: item!,
})
);
await Promise.all([...updateAssignToolPromises, ...logRecordPromises]);
});
return data!;
}
async update(
data: Partial<Tool[]>,
userId: UserId
): Promise<Partial<Tool[]>> {
await db.transaction(async (tx) => {
const updatesPromises = data.map((item) => {
return db
.update(tool)
.set(item!)
.where(eq(tool.id, item?.id!))
.returning();
});
const logRecordPromises = data.map((item) =>
createLogRecord(tx, {
userId: userId.value,
modifiedItem: `Tool-${item?.name}-actualizada`,
eventType: "crear",
tableName: "tool",
item: item!,
})
);
await Promise.all([...updatesPromises, ...logRecordPromises]);
});
return data;
}
}
export const defaultToolRepository = new ToolRepositoryImpl();