🚧 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 { generateUUIDv7 } from "../../../helpers/databases/uuidv7";
|
||||||
import { MediaFullInfoResponse } from "../types/mediaFullInfo.type";
|
import { MediaFullInfoResponse } from "../types/mediaFullInfo.type";
|
||||||
import { SystemAccountId } from "../../../config/account/system";
|
import { SystemAccountId } from "../../../config/account/system";
|
||||||
|
import { bulkInsertMediaProducerStudioLicensorRepository } from "./bulkInsertMediaProducerStudioLicensor.repository";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Media Payload Construction and Upsert
|
* Media Payload Construction and Upsert
|
||||||
@ -109,10 +110,41 @@ export const InsertMediaRepository = async ({ payload }: { payload: MediaFullInf
|
|||||||
broadcast_day: payload.broadcast.day,
|
broadcast_day: payload.broadcast.day,
|
||||||
};
|
};
|
||||||
|
|
||||||
return await prisma.media.upsert({
|
const producerPayload = [
|
||||||
where: { mal_id: payload.mal_id },
|
...payload.producers.map((producer) => ({
|
||||||
create: constructMediaPayload,
|
mal_id: producer.mal_id,
|
||||||
update: constructMediaPayload,
|
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) {
|
} catch (error) {
|
||||||
throw new AppError(500, "Failed to insert media", error);
|
throw new AppError(500, "Failed to insert media", error);
|
||||||
|
|||||||
@ -33,13 +33,13 @@ interface Data {
|
|||||||
season: media_season;
|
season: media_season;
|
||||||
year: number;
|
year: number;
|
||||||
broadcast: Broadcast;
|
broadcast: Broadcast;
|
||||||
producers: Genre[];
|
producers: GenreOrProducer[];
|
||||||
licensors: unknown[];
|
licensors: GenreOrProducer[];
|
||||||
studios: Genre[];
|
studios: GenreOrProducer[];
|
||||||
genres: Genre[];
|
genres: GenreOrProducer[];
|
||||||
explicit_genres: unknown[];
|
explicit_genres: GenreOrProducer[];
|
||||||
themes: Genre[];
|
themes: GenreOrProducer[];
|
||||||
demographics: unknown[];
|
demographics: GenreOrProducer[];
|
||||||
relations: Relation[];
|
relations: Relation[];
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
external: External[];
|
external: External[];
|
||||||
@ -76,18 +76,13 @@ interface External {
|
|||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Genre {
|
export interface GenreOrProducer {
|
||||||
mal_id: number;
|
mal_id: number;
|
||||||
type: Type;
|
type: string;
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Type {
|
|
||||||
Anime = "anime",
|
|
||||||
Manga = "manga",
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Image {
|
interface Image {
|
||||||
image_url: string;
|
image_url: string;
|
||||||
small_image_url: string;
|
small_image_url: string;
|
||||||
@ -96,7 +91,7 @@ interface Image {
|
|||||||
|
|
||||||
interface Relation {
|
interface Relation {
|
||||||
relation: string;
|
relation: string;
|
||||||
entry: Genre[];
|
entry: GenreOrProducer[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Theme {
|
interface Theme {
|
||||||
|
|||||||
Reference in New Issue
Block a user