Files
whyrating/packages/api/src/modules/admin/organizations/queries.ts
2026-02-04 01:55:00 +01:00

109 lines
2.8 KiB
TypeScript

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<number>`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<number>`CAST(COUNT(${member.id}) AS INTEGER)`.as(
"members",
),
total: sql<number>`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<number>`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
);
};