import dayjs from "dayjs"; import { and, asc, between, count, eq, getOrderByFromSort, ilike, sql, } from "@turbostarter/db"; import { organization, member } from "@turbostarter/db/schema"; import { db } from "@turbostarter/db/server"; import type { GetOrganizationsInput } from "../../../schema"; export const getOrganizationsCount = async () => db .select({ count: count() }) .from(organization) .then((res) => res[0]?.count ?? 0); export const getOrganizations = async (input: GetOrganizationsInput) => { const offset = (input.page - 1) * input.perPage; const where = and( input.q ? ilike(organization.name, `%${input.q}%`) : undefined, input.createdAt ? between( organization.createdAt, dayjs(input.createdAt[0]).startOf("day").toDate(), dayjs(input.createdAt[1]).endOf("day").toDate(), ) : undefined, ); const having = input.members ? between( sql`CAST(COUNT(${member.id}) AS INTEGER)`, input.members[0], input.members[1], ) : undefined; const orderBy = input.sort && input.sort.length > 0 ? input.sort.flatMap((s) => { const field = s.id.split(/[_.]/).pop() ?? s.id; if (field === "members") { return [s.desc ? sql`members DESC` : sql`members ASC`]; } return getOrderByFromSort({ sort: [s], defaultSchema: organization }); }) : [asc(organization.name)]; return db.transaction(async (tx) => { const results = await tx .select({ id: organization.id, name: organization.name, slug: organization.slug, logo: organization.logo, createdAt: organization.createdAt, members: sql`CAST(COUNT(${member.id}) AS INTEGER)`.as( "members", ), total: sql`COUNT(*) OVER()`.mapWith(Number).as("total"), }) .from(organization) .leftJoin(member, eq(member.organizationId, organization.id)) .where(where) .groupBy(organization.id) .having(having) .limit(input.perPage) .offset(offset) .orderBy(...orderBy); const membersMax = await tx .select({ members: sql`CAST(COUNT(${member.id}) AS INTEGER)`.as( "members", ), }) .from(member) .groupBy(member.organizationId) .orderBy(sql`members DESC`) .limit(1) .then((res) => res[0]?.members ?? 0); const data = results.map(({ total: _, ...rest }) => rest); const total = results[0]?.total ?? 0; return { data, total, max: { members: membersMax }, }; }); }; export const getOrganization = async ({ id }: { id: string }) => { return ( (await db.query.organization.findFirst({ where: eq(organization.id, id), })) ?? null ); };