postiz/libraries/nestjs-libraries/src/database/prisma/posts/posts.repository.ts

508 lines
11 KiB
TypeScript

import { PrismaRepository } from '@gitroom/nestjs-libraries/database/prisma/prisma.service';
import { Injectable } from '@nestjs/common';
import { Post as PostBody } from '@gitroom/nestjs-libraries/dtos/posts/create.post.dto';
import { APPROVED_SUBMIT_FOR_ORDER, Post, State } from '@prisma/client';
import { GetPostsDto } from '@gitroom/nestjs-libraries/dtos/posts/get.posts.dto';
import dayjs from 'dayjs';
import isoWeek from 'dayjs/plugin/isoWeek';
import weekOfYear from 'dayjs/plugin/weekOfYear';
import { v4 as uuidv4 } from 'uuid';
dayjs.extend(isoWeek);
dayjs.extend(weekOfYear);
@Injectable()
export class PostsRepository {
constructor(
private _post: PrismaRepository<'post'>,
private _popularPosts: PrismaRepository<'popularPosts'>,
private _comments: PrismaRepository<'comments'>
) {}
getOldPosts(orgId: string, date: string) {
return this._post.model.post.findMany({
where: {
organizationId: orgId,
publishDate: {
lte: dayjs(date).toDate(),
},
deletedAt: null,
parentPostId: null,
},
orderBy: {
publishDate: 'desc',
},
select: {
id: true,
content: true,
publishDate: true,
releaseURL: true,
state: true,
integration: {
select: {
id: true,
name: true,
providerIdentifier: true,
picture: true,
type: true,
},
},
},
});
}
getPostUrls(orgId: string, ids: string[]) {
return this._post.model.post.findMany({
where: {
organizationId: orgId,
id: {
in: ids,
},
},
select: {
id: true,
releaseURL: true,
},
});
}
getPosts(orgId: string, query: GetPostsDto) {
const dateYear = dayjs().year(query.year);
const date =
query.display === 'day'
? dateYear.isoWeek(query.week).day(query.day)
: query.display === 'week'
? dateYear.isoWeek(query.week)
: dateYear.month(query.month - 1);
const startDate = (
query.display === 'day'
? date.startOf('day')
: query.display === 'week'
? date.startOf('isoWeek')
: date.startOf('month')
)
.subtract(2, 'hours')
.toDate();
const endDate = (
query.display === 'day'
? date.endOf('day')
: query.display === 'week'
? date.endOf('isoWeek')
: date.endOf('month')
)
.add(2, 'hours')
.toDate();
return this._post.model.post.findMany({
where: {
OR: [
{
organizationId: orgId,
},
{
submittedForOrganizationId: orgId,
},
],
publishDate: {
gte: startDate,
lte: endDate,
},
deletedAt: null,
parentPostId: null,
...query.customer ? {
integration: {
customerId: query.customer,
}
}: {},
},
select: {
id: true,
content: true,
publishDate: true,
releaseURL: true,
submittedForOrganizationId: true,
submittedForOrderId: true,
state: true,
integration: {
select: {
id: true,
providerIdentifier: true,
name: true,
picture: true,
},
},
},
});
}
async deletePost(orgId: string, group: string) {
await this._post.model.post.updateMany({
where: {
organizationId: orgId,
group,
},
data: {
deletedAt: new Date(),
},
});
return this._post.model.post.findFirst({
where: {
organizationId: orgId,
group,
parentPostId: null,
},
select: {
id: true,
},
});
}
getPost(
id: string,
includeIntegration = false,
orgId?: string,
isFirst?: boolean
) {
return this._post.model.post.findUnique({
where: {
id,
...(orgId ? { organizationId: orgId } : {}),
deletedAt: null,
},
include: {
...(includeIntegration
? {
integration: true,
}
: {}),
childrenPost: true,
},
});
}
updatePost(id: string, postId: string, releaseURL: string) {
return this._post.model.post.update({
where: {
id,
},
data: {
state: 'PUBLISHED',
releaseURL,
releaseId: postId,
},
});
}
changeState(id: string, state: State, err?: string) {
return this._post.model.post.update({
where: {
id,
},
data: {
state,
error: typeof err === 'string' ? err : JSON.stringify(err),
},
});
}
async changeDate(orgId: string, id: string, date: string) {
return this._post.model.post.update({
where: {
organizationId: orgId,
id,
},
data: {
publishDate: dayjs(date).toDate(),
},
});
}
countPostsFromDay(orgId: string, date: Date) {
return this._post.model.post.count({
where: {
organizationId: orgId,
publishDate: {
gte: date,
},
OR: [
{
deletedAt: null,
state: {
in: ['QUEUE'],
},
},
{
state: 'PUBLISHED',
},
],
},
});
}
async createOrUpdatePost(
state: 'draft' | 'schedule' | 'now',
orgId: string,
date: string,
body: PostBody
) {
const posts: Post[] = [];
const uuid = uuidv4();
for (const value of body.value) {
const updateData = (type: 'create' | 'update') => ({
publishDate: dayjs(date).toDate(),
integration: {
connect: {
id: body.integration.id,
organizationId: orgId,
},
},
...(posts?.[posts.length - 1]?.id
? {
parentPost: {
connect: {
id: posts[posts.length - 1]?.id,
},
},
}
: type === 'update'
? {
parentPost: {
disconnect: true,
},
}
: {}),
content: value.content,
group: uuid,
approvedSubmitForOrder: APPROVED_SUBMIT_FOR_ORDER.NO,
state: state === 'draft' ? ('DRAFT' as const) : ('QUEUE' as const),
image: JSON.stringify(value.image),
settings: JSON.stringify(body.settings),
organization: {
connect: {
id: orgId,
},
},
});
posts.push(
await this._post.model.post.upsert({
where: {
id: value.id || uuidv4(),
},
create: { ...updateData('create') },
update: {
...updateData('update'),
lastMessage: {
disconnect: true,
},
submittedForOrder: {
disconnect: true,
},
},
})
);
}
const previousPost = body.group
? (
await this._post.model.post.findFirst({
where: {
group: body.group,
deletedAt: null,
parentPostId: null,
},
select: {
id: true,
},
})
)?.id!
: undefined;
if (body.group) {
await this._post.model.post.updateMany({
where: {
group: body.group,
deletedAt: null,
},
data: {
parentPostId: null,
deletedAt: new Date(),
},
});
}
return { previousPost, posts };
}
async submit(id: string, order: string, buyerOrganizationId: string) {
return this._post.model.post.update({
where: {
id,
},
data: {
submittedForOrderId: order,
approvedSubmitForOrder: 'WAITING_CONFIRMATION',
submittedForOrganizationId: buyerOrganizationId,
},
select: {
id: true,
description: true,
submittedForOrder: {
select: {
messageGroupId: true,
},
},
},
});
}
updateMessage(id: string, messageId: string) {
return this._post.model.post.update({
where: {
id,
},
data: {
lastMessageId: messageId,
},
});
}
getPostById(id: string, org?: string) {
return this._post.model.post.findUnique({
where: {
id,
...(org ? { organizationId: org } : {}),
},
include: {
integration: true,
submittedForOrder: {
include: {
posts: {
where: {
state: 'PUBLISHED',
},
},
ordersItems: true,
seller: {
select: {
id: true,
account: true,
},
},
},
},
},
});
}
findAllExistingCategories() {
return this._popularPosts.model.popularPosts.findMany({
select: {
category: true,
},
distinct: ['category'],
});
}
findAllExistingTopicsOfCategory(category: string) {
return this._popularPosts.model.popularPosts.findMany({
where: {
category,
},
select: {
topic: true,
},
distinct: ['topic'],
});
}
findPopularPosts(category: string, topic?: string) {
return this._popularPosts.model.popularPosts.findMany({
where: {
category,
...(topic ? { topic } : {}),
},
select: {
content: true,
hook: true,
},
});
}
createPopularPosts(post: {
category: string;
topic: string;
content: string;
hook: string;
}) {
return this._popularPosts.model.popularPosts.create({
data: {
category: 'category',
topic: 'topic',
content: 'content',
hook: 'hook',
},
});
}
async getPostsCountsByDates(
orgId: string,
times: number[],
date: dayjs.Dayjs
) {
const dates = await this._post.model.post.findMany({
where: {
deletedAt: null,
organizationId: orgId,
publishDate: {
in: times.map((time) => {
return date.clone().add(time, 'minutes').toDate();
}),
},
},
});
return times.filter(
(time) =>
date.clone().add(time, 'minutes').isAfter(dayjs.utc()) &&
!dates.find((dateFind) => {
return (
dayjs
.utc(dateFind.publishDate)
.diff(date.clone().startOf('day'), 'minutes') == time
);
})
);
}
async getComments(postId: string) {
return this._comments.model.comments.findMany({
where: {
postId,
},
orderBy: {
createdAt: 'asc',
},
});
}
createComment(
orgId: string,
userId: string,
postId: string,
content: string
) {
return this._comments.model.comments.create({
data: {
organizationId: orgId,
userId,
postId,
content,
},
});
}
}