/home/bdqbpbxa/dev-subdomains/admin.pixory.goodface.com.ua/src/api/cart/controllers/cart.ts
import { factories } from '@strapi/strapi'
import { Context } from 'koa'
import { ValidationError } from 'yup';
import { setCartSchema } from '../common/schemas/set-cart';
import { addCartSchema } from '../common/schemas/add-cart';
import { SetCart } from '../common/types/set-cart';
import { ProjectService } from 'src/api/project/services/project';
import { AddCart } from '../common/types/add-cart';
import { Project } from 'src/api/project/common/types/project';
import { BookTypeService } from 'src/api/book-type/services/book-type';
import { BookSizeService } from 'src/api/book-size/services/book-size';
import { PaperFinishService } from 'src/api/paper-finish/services/paper-finish';
import { CartService } from '../services/cart';
import { OrderedProjectService } from 'src/api/ordered-project/services/ordered-project';
export default factories.createCoreController('api::cart.cart', ({ strapi }) => ({
async find(ctx: Context) {
if (!ctx.state.user) {
return ctx.unauthorized('You must be authenticated to update user information');
}
const cartService = new CartService(strapi);
const cart = await cartService.findOrCreate(ctx.state.user.id);
return ctx.send(cart);
},
async add(ctx: Context) {
try {
if (!ctx.state.user) {
return ctx.unauthorized('You must be authenticated to update user information');
}
addCartSchema.validateSync(ctx.request?.body || {});
const { projectId } = ctx.request.body as AddCart;
const cartService = new CartService(strapi);
const projectService = new ProjectService(strapi);
const projectData = await projectService.getProjectData(projectId);
const {bookType, bookSize, paperFinish} = await cartService.getBookAttributes(projectData);
if (!bookType || !bookSize || !paperFinish) {
strapi.log.error(`Project attributes are not fully mapped in the system. Project data: ${projectData}`);
return ctx.badRequest('Project attributes are not fully mapped in the system. Contact support.');
}
const cart = await cartService.findOrCreate(ctx.state.user.id);
let project = await strapi.db.query('api::project.project').findOne({
where: { printboxProjectUuid: projectData.uuid }
}) as Project;
if (!project) {
project = await strapi.db.query('api::project.project').create({
data: {
cart: cart.id,
user: ctx.state.user.id,
title: projectData.name,
printboxProjectUuid: projectData.uuid,
priceDiscounted: projectData.params[0].price_net,
price: projectData.params[0].price_gross,
bookType: bookType?.id,
bookSize: bookSize?.id,
paperFinish: paperFinish?.id,
},
populate: {
bookType: true,
bookSize: true,
paperFinish: true,
}
}) as Project;
}
const existingOrderedProject = await strapi.db.query('api::ordered-project.ordered-project').findOne({
where: { project: project.id }
});
const orderedProjectService = new OrderedProjectService(strapi);
if (existingOrderedProject) {
await orderedProjectService.increment(existingOrderedProject.id, existingOrderedProject.quantity);
} else {
const orderedProject = await orderedProjectService.create(project.id, cart.id);
await cartService.appendOrderedProject(cart.id, [orderedProject.id]);
}
ctx.send(await cartService.findOrCreate(ctx.state.user.id));
} catch (error) {
if (error instanceof ValidationError) {
return ctx.badRequest('Validation error', error.errors);
}
strapi.log.error('Error updating user:', error);
return ctx.internalServerError('An error occurred while updating the user');
}
},
async set(ctx: Context) {
try {
if (!ctx.state.user) {
return ctx.unauthorized('You must be authenticated to update user information');
}
setCartSchema.validateSync(ctx.request.body || {});
let { projects } = ctx.request.body as SetCart;
projects = projects.reduce((acc, project) => {
const existingProject = acc.find(p => p.projectId === project.projectId);
if (existingProject) {
existingProject.quantity += project.quantity;
} else {
acc.push({ ...project });
}
return acc;
}, [] as { projectId: string; quantity: number }[]);
const cartService = new CartService(strapi);
const cart = await cartService.findOrCreate(ctx.state.user.id);
const projectService = new ProjectService(strapi);
let projectsPrintboxData = await projectService.getProjectsData(projects.map(p => p.projectId));
const nonEmptyProjectData = projectsPrintboxData.filter(p => p !== null);
const existingProjects = await strapi.db.query('api::project.project').findMany({
where: { printboxProjectUuid: { $in: projectsPrintboxData.map(p => p.uuid) } }
});
const existingProjectsUuids = existingProjects.map(p => p.printboxProjectUuid);
const projectsDataToCreate = nonEmptyProjectData.filter(p => !existingProjectsUuids.includes(p.uuid));
const projectsData = await Promise.all(projectsDataToCreate.map(async (project) => {
const {bookType, bookSize, paperFinish} = await cartService.getBookAttributes(project);
if (!bookType || !bookSize || !paperFinish) {
strapi.log.error(`Project attributes are not fully mapped in the system. Project data: ${project}`);
return ctx.badRequest('Project attributes are not fully mapped in the system. Contact support.');
}
return {
cart: cart.id,
user: ctx.state.user.id,
title: project.name,
printboxProjectUuid: project.uuid,
priceDiscounted: project.params[0].price_net,
price: project.params[0].price_gross,
bookType: bookType?.id,
bookSize: bookSize?.id,
paperFinish: paperFinish?.id,
}
}));
await strapi.db.query('api::ordered-project.ordered-project').delete({
where: { project: {
user: ctx.state.user.id
}}
});
if (projectsData.length > 0) {
await strapi.db.query('api::project.project').createMany({ data: projectsData });
}
const cartedProjects = await strapi.db.query('api::project.project').findMany({
where: { printboxProjectUuid: { $in: projectsPrintboxData.map(p => p.uuid) } },
});
const orderedProjectsData = projects.map((project) => ({
quantity: project.quantity,
project: {
connect: cartedProjects.filter(p => p.printboxProjectUuid === project.projectId).map(p => p.id)[0]
},
}));
const createdOrderedProjects = await Promise.all(orderedProjectsData.map(async (data) => {
return await strapi.db.query('api::ordered-project.ordered-project').create({
data
});
}));
await cartService.appendOrderedProject(cart.id, createdOrderedProjects.map(p => p.id));
ctx.send(await cartService.findOrCreate(ctx.state.user.id));
} catch (error) {
if (error instanceof ValidationError) {
return ctx.badRequest('Validation error', error.errors);
}
strapi.log.error('Error updating user:', error);
return ctx.internalServerError('An error occurred while updating the user');
}
}
}));