🚧 wip: update bulk insert producer in media
This commit is contained in:
@ -0,0 +1,74 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { GenreOrProducer, MediaFullInfoResponse } from "../types/mediaFullInfo.type";
|
||||
import { SystemAccountId } from "../../../config/account/system";
|
||||
import { status } from "elysia";
|
||||
|
||||
export const bulkInsertMediaProducerStudioLicensorRepository = async (
|
||||
tx: Prisma.TransactionClient,
|
||||
media_id: string,
|
||||
payload: (GenreOrProducer & { status: "producer" | "licensor" | "studio" })[],
|
||||
) => {
|
||||
await tx.producer.createMany({
|
||||
data: payload.map((p) => ({
|
||||
mal_id: p.mal_id,
|
||||
type: p.type,
|
||||
name: p.name,
|
||||
url: p.url,
|
||||
created_by_id: SystemAccountId,
|
||||
})),
|
||||
skipDuplicates: true,
|
||||
});
|
||||
|
||||
const insertedProducers = (
|
||||
await tx.producer.findMany({
|
||||
where: {
|
||||
mal_id: {
|
||||
in: payload.map((p) => p.mal_id),
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
mal_id: true,
|
||||
},
|
||||
})
|
||||
).map((producer) => {
|
||||
const statusProducer = payload.find((p) => p.mal_id === producer.mal_id)?.status;
|
||||
return {
|
||||
id: producer.id,
|
||||
mal_id: producer.mal_id,
|
||||
status: statusProducer,
|
||||
};
|
||||
});
|
||||
|
||||
await tx.mediaProducer.createMany({
|
||||
data: insertedProducers
|
||||
.filter((p) => p.status === "producer")
|
||||
.map((producer) => ({
|
||||
media_id,
|
||||
producer_id: producer.id,
|
||||
})),
|
||||
skipDuplicates: true,
|
||||
});
|
||||
|
||||
await tx.mediaLicensor.createMany({
|
||||
data: insertedProducers
|
||||
.filter((p) => p.status === "licensor")
|
||||
.map((producer) => ({
|
||||
media_id,
|
||||
licensor_id: producer.id,
|
||||
})),
|
||||
skipDuplicates: true,
|
||||
});
|
||||
|
||||
await tx.mediaStudio.createMany({
|
||||
data: insertedProducers
|
||||
.filter((p) => p.status === "studio")
|
||||
.map((producer) => ({
|
||||
media_id,
|
||||
studio_id: producer.id,
|
||||
})),
|
||||
skipDuplicates: true,
|
||||
});
|
||||
|
||||
return insertedProducers;
|
||||
};
|
||||
@ -1,69 +0,0 @@
|
||||
import { SystemAccountId } from "../../../config/account/system";
|
||||
import { generateSlug } from "../../../helpers/characters/generateSlug";
|
||||
import { generateUUIDv7 } from "../../../helpers/databases/uuidv7";
|
||||
import { AppError } from "../../../helpers/error/instances/app";
|
||||
import { prisma } from "../../../utils/databases/prisma/connection";
|
||||
import { MediaFullInfoResponse } from "../types/mediaFullInfo.type";
|
||||
|
||||
/**
|
||||
* Studios Insertion
|
||||
*
|
||||
* This section manages the insertion of studios associated with the media.
|
||||
* It processes each studio listed in the media data, generating a slug for
|
||||
* each and performing an upsert operation to either create or update the
|
||||
* studio record in the database. The IDs of the inserted or updated studios
|
||||
* are collected for later association with the media.
|
||||
*
|
||||
* @param data - The full media data containing studios information.
|
||||
* @returns An array of IDs of the inserted or updated studios.
|
||||
*/
|
||||
export const bulkInsertStudiosRepository = async (
|
||||
data: MediaFullInfoResponse,
|
||||
) => {
|
||||
try {
|
||||
const studioIds: string[] = [];
|
||||
for (const studio of data.data.studios) {
|
||||
const slug = (await generateSlug(studio.name)) as string;
|
||||
const studioPayload = {
|
||||
name: studio.name,
|
||||
malId: studio.mal_id,
|
||||
linkAbout: studio.url,
|
||||
createdBy: SystemAccountId,
|
||||
slug,
|
||||
};
|
||||
const insertedStudio = await prisma.studio.upsert({
|
||||
where: { slug },
|
||||
create: {
|
||||
id: generateUUIDv7(),
|
||||
...studioPayload,
|
||||
},
|
||||
update: studioPayload,
|
||||
select: { id: true },
|
||||
});
|
||||
studioIds.push(insertedStudio.id);
|
||||
}
|
||||
for (const studio of data.data.producers) {
|
||||
const slug = (await generateSlug(studio.name)) as string;
|
||||
const studioPayload = {
|
||||
name: studio.name,
|
||||
malId: studio.mal_id,
|
||||
linkAbout: studio.url,
|
||||
createdBy: SystemAccountId,
|
||||
slug,
|
||||
};
|
||||
const insertedStudio = await prisma.studio.upsert({
|
||||
where: { slug },
|
||||
create: {
|
||||
id: generateUUIDv7(),
|
||||
...studioPayload,
|
||||
},
|
||||
update: studioPayload,
|
||||
select: { id: true },
|
||||
});
|
||||
studioIds.push(insertedStudio.id);
|
||||
}
|
||||
return studioIds;
|
||||
} catch (error) {
|
||||
throw new AppError(500, "Failed to insert studios", error);
|
||||
}
|
||||
};
|
||||
@ -4,6 +4,7 @@ import { prisma } from "../../../utils/databases/prisma/connection";
|
||||
import { generateUUIDv7 } from "../../../helpers/databases/uuidv7";
|
||||
import { MediaFullInfoResponse } from "../types/mediaFullInfo.type";
|
||||
import { SystemAccountId } from "../../../config/account/system";
|
||||
import { bulkInsertMediaProducerStudioLicensorRepository } from "./bulkInsertMediaProducerStudioLicensor.repository";
|
||||
|
||||
/**
|
||||
* Media Payload Construction and Upsert
|
||||
@ -109,10 +110,41 @@ export const InsertMediaRepository = async ({ payload }: { payload: MediaFullInf
|
||||
broadcast_day: payload.broadcast.day,
|
||||
};
|
||||
|
||||
return await prisma.media.upsert({
|
||||
where: { mal_id: payload.mal_id },
|
||||
create: constructMediaPayload,
|
||||
update: constructMediaPayload,
|
||||
const producerPayload = [
|
||||
...payload.producers.map((producer) => ({
|
||||
mal_id: producer.mal_id,
|
||||
type: producer.type,
|
||||
name: producer.name,
|
||||
url: producer.url,
|
||||
status: "producer" as const,
|
||||
})),
|
||||
...payload.licensors.map((licensor) => ({
|
||||
mal_id: licensor.mal_id,
|
||||
type: licensor.type,
|
||||
name: licensor.name,
|
||||
url: licensor.url,
|
||||
status: "licensor" as const,
|
||||
})),
|
||||
...payload.studios.map((studio) => ({
|
||||
mal_id: studio.mal_id,
|
||||
type: studio.type,
|
||||
name: studio.name,
|
||||
url: studio.url,
|
||||
status: "studio" as const,
|
||||
})),
|
||||
];
|
||||
|
||||
prisma.$transaction(async (tx) => {
|
||||
const media = await tx.media.upsert({
|
||||
where: { mal_id: payload.mal_id },
|
||||
create: constructMediaPayload,
|
||||
update: constructMediaPayload,
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
|
||||
await bulkInsertMediaProducerStudioLicensorRepository(tx, media.id, producerPayload);
|
||||
});
|
||||
} catch (error) {
|
||||
throw new AppError(500, "Failed to insert media", error);
|
||||
|
||||
@ -33,13 +33,13 @@ interface Data {
|
||||
season: media_season;
|
||||
year: number;
|
||||
broadcast: Broadcast;
|
||||
producers: Genre[];
|
||||
licensors: unknown[];
|
||||
studios: Genre[];
|
||||
genres: Genre[];
|
||||
explicit_genres: unknown[];
|
||||
themes: Genre[];
|
||||
demographics: unknown[];
|
||||
producers: GenreOrProducer[];
|
||||
licensors: GenreOrProducer[];
|
||||
studios: GenreOrProducer[];
|
||||
genres: GenreOrProducer[];
|
||||
explicit_genres: GenreOrProducer[];
|
||||
themes: GenreOrProducer[];
|
||||
demographics: GenreOrProducer[];
|
||||
relations: Relation[];
|
||||
theme: Theme;
|
||||
external: External[];
|
||||
@ -76,18 +76,13 @@ interface External {
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface Genre {
|
||||
export interface GenreOrProducer {
|
||||
mal_id: number;
|
||||
type: Type;
|
||||
type: string;
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
enum Type {
|
||||
Anime = "anime",
|
||||
Manga = "manga",
|
||||
}
|
||||
|
||||
interface Image {
|
||||
image_url: string;
|
||||
small_image_url: string;
|
||||
@ -96,7 +91,7 @@ interface Image {
|
||||
|
||||
interface Relation {
|
||||
relation: string;
|
||||
entry: Genre[];
|
||||
entry: GenreOrProducer[];
|
||||
}
|
||||
|
||||
interface Theme {
|
||||
|
||||
Reference in New Issue
Block a user