task-managment / src / server / tool / infrastructure / repositories-impl.ts
repositories-impl.ts
Raw
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();