feat: whyrating - initial project from turbostarter boilerplate
This commit is contained in:
108
packages/api/src/modules/admin/organizations/queries.ts
Normal file
108
packages/api/src/modules/admin/organizations/queries.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
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
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user