import _ from 'lodash'; import { ApolloError } from 'apollo-server-lambda'; import { Resolver, Authorized, Ctx, Query } from 'type-graphql'; import { Mutation, Arg } from 'type-graphql'; import { ApolloContext } from '@seed/interfaces/context'; import { updatePaymentIntent } from '@services/module-payments/helpers/payments.helpers'; import OrderEngineModel from '../../order.model'; import PromoModel, { validatePromo } from '@services/module-payments/functions/promos/promo.model'; import { PaymentIntentInfo } from '@services/module-payments/components/components.payments'; import { addToCart, getCurrentCartOrder } from '@services/module-payments/functions/orders/services/CartService'; import { LineItemBaseSchema } from '@src/orders/components/line.schema'; import { OrderEngineSchema } from '../../schemas/order.schema'; import { CartEngineAddCountryCodeSchema, CartEngineAddPromoSchema, CartEngineUpdateOrDeleteSchema, CartEngineUpdateSchema, } from '../schemas/cart.schema.inputs'; import { OrderNewInputSchema } from '@src/orders/components/components.cart'; @Resolver(OrderEngineSchema) export default class CartEngineResolver { /* ██████╗ ██╗ ██╗███████╗██████╗ ██╗ ██╗ ██╔═══██╗██║ ██║██╔════╝██╔══██╗╚██╗ ██╔╝ ██║ ██║██║ ██║█████╗ ██████╔╝ ╚████╔╝ ██║▄▄ ██║██║ ██║██╔══╝ ██╔══██╗ ╚██╔╝ ╚██████╔╝╚██████╔╝███████╗██║ ██║ ██║ ╚══▀▀═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ */ @Query(() => OrderEngineSchema) @Authorized() async cartsGetMe(@Ctx() ctx: ApolloContext, @Arg('input', { nullable: true }) input?: OrderNewInputSchema): Promise { try { return await getCurrentCartOrder(ctx, input); } catch (error) { throw error; } } /* ███╗ ███╗██╗ ██╗████████╗ █████╗ ████████╗ ██████╗ ██████╗ ███████╗ ████╗ ████║██║ ██║╚══██╔══╝██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗██╔════╝ ██╔████╔██║██║ ██║ ██║ ███████║ ██║ ██║ ██║██████╔╝███████╗ ██║╚██╔╝██║██║ ██║ ██║ ██╔══██║ ██║ ██║ ██║██╔══██╗╚════██║ ██║ ╚═╝ ██║╚██████╔╝ ██║ ██║ ██║ ██║ ╚██████╔╝██║ ██║███████║ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ */ @Mutation(() => OrderEngineSchema) @Authorized() async cartsAddOneItem(@Arg('input') input: LineItemBaseSchema, @Ctx() ctx: ApolloContext): Promise { return await addToCart(input, ctx); } @Mutation(() => OrderEngineSchema) @Authorized() async cartsUpdateOneItem(@Arg('input') input: CartEngineUpdateSchema, @Ctx() ctx: ApolloContext): Promise { const account = ctx.ctx.user; const orderModel = new OrderEngineModel(); try { const currentCartOrder = await getCurrentCartOrder(ctx); // Check the lines const lineIndex = _.findIndex(currentCartOrder.lines, function(o) { if (o.productId == input.productId && _.isEqual(JSON.parse(JSON.stringify(o.options)), JSON.parse(JSON.stringify(o.options)))) return true; else return false; }); if (lineIndex === -1) throw new ApolloError('cart.item.notFound', '404', { productId: input.productId }); if (input.newQuantity == 0) currentCartOrder.lines.splice(lineIndex, 1); else { // Update the quantity currentCartOrder.lines[lineIndex].quantity = input.newQuantity; } const paymentIntentUpdated: PaymentIntentInfo = await updatePaymentIntent(currentCartOrder.paymentIntent, { amount: await currentCartOrder.finalPrice(ctx), currency: currentCartOrder.currency, account, }); return await orderModel.updateOneCustom({ query: { _id: currentCartOrder._id }, updateRequest: { $set: { paymentIntent: paymentIntentUpdated, lines: currentCartOrder.lines, }, }, ctx, }); } catch (error) { throw error; } } @Mutation(() => OrderEngineSchema) @Authorized() async cartsUpdateOrDeleteOneItem(@Arg('input') input: CartEngineUpdateOrDeleteSchema, @Ctx() ctx: ApolloContext): Promise { const account = ctx.ctx.user; const orderModel = new OrderEngineModel(); const { lineId, newQuantity } = input; try { const currentCartOrder = await getCurrentCartOrder(ctx); // Check the lines const lineIndex = _.findIndex(currentCartOrder.lines, { _id: lineId }); if (lineIndex === -1) throw new ApolloError('cart.line.notFound', '404', { lineId: input.lineId }); if (newQuantity == 0) currentCartOrder.lines.splice(lineIndex, 1); else { // Update the quantity currentCartOrder.lines[lineIndex].quantity = newQuantity; } const paymentIntentUpdated: PaymentIntentInfo = await updatePaymentIntent(currentCartOrder.paymentIntent, { amount: await currentCartOrder.finalPrice(ctx), currency: currentCartOrder.currency, account, }); return await orderModel.updateOneCustom({ query: { _id: currentCartOrder._id }, updateRequest: { $set: { paymentIntent: paymentIntentUpdated, lines: currentCartOrder.lines, }, }, ctx, }); } catch (error) { throw error; } } @Mutation(() => OrderEngineSchema) @Authorized() async cartsEmpty(@Ctx() ctx: ApolloContext): Promise { const orderModel = new OrderEngineModel(); try { const currentCartOrder = await getCurrentCartOrder(ctx); return await orderModel.updateOneCustom({ query: { _id: currentCartOrder._id }, updateRequest: { $set: { lines: [], }, $unset: { promoId: '', countryCode: '', locale: '', }, }, ctx, }); } catch (error) { throw error; } } @Mutation(() => OrderEngineSchema) @Authorized() async cartAddCountryCode(@Arg('input') input: CartEngineAddCountryCodeSchema, @Ctx() ctx: ApolloContext): Promise { const orderModel = new OrderEngineModel(); try { const currentCartOrder = await getCurrentCartOrder(ctx); if (!currentCartOrder) throw new ApolloError('cart.notFound', '404'); const lines = currentCartOrder.lines; lines.map((line) => { if (line.localeInfo) return (line.localeInfo.countryCode = input.countryCode); return (line.localeInfo = { countryCode: input.countryCode }); }); return await orderModel.updateOneCustom({ query: { _id: currentCartOrder._id }, updateRequest: { $set: { countryCode: input.countryCode, lines }, }, ctx, }); } catch (error) { throw error; } } @Mutation(() => OrderEngineSchema) @Authorized() async cartAddPromo(@Arg('input') input: CartEngineAddPromoSchema, @Ctx() ctx: ApolloContext): Promise { const orderModel = new OrderEngineModel(); const promoModel = new PromoModel(); try { const currentCartOrder = await getCurrentCartOrder(ctx); if (!currentCartOrder) throw new ApolloError('cart.notFound', '404'); await promoModel.getOne({ code: input.promoCode }, ctx); await validatePromo(input.promoCode, ctx); const lines = currentCartOrder.lines; lines.map((line) => { return (line.promoId = promoModel._id); }); const paymentIntentUpdated: PaymentIntentInfo = await updatePaymentIntent(currentCartOrder.paymentIntent, { amount: await currentCartOrder.finalPrice(ctx), currency: currentCartOrder.currency, account: ctx.ctx.user, }); return await orderModel.updateOneCustom({ query: { _id: currentCartOrder._id }, updateRequest: { // finalPrice: currentCart.finalPrice, $set: { promoId: promoModel._id, lines, paymentIntent: paymentIntentUpdated }, }, ctx, }); } catch (error) { throw error; } } @Mutation(() => OrderEngineSchema) @Authorized() async cartRemovePromo(@Ctx() ctx: ApolloContext): Promise { const orderModel = new OrderEngineModel(); try { const currentCartOrder = await getCurrentCartOrder(ctx); if (!currentCartOrder) throw new ApolloError('cart.notFound', '404'); const lines = currentCartOrder.lines; lines.forEach((line) => { delete line.promoId; }); const paymentIntentUpdated: PaymentIntentInfo = await updatePaymentIntent(currentCartOrder.paymentIntent, { amount: await currentCartOrder.finalPrice(ctx), currency: currentCartOrder.currency, account: ctx.ctx.user, }); return await orderModel.updateOneCustom({ query: { _id: currentCartOrder._id }, updateRequest: { $unset: { promoId: '', }, $set: { lines, paymentIntent: paymentIntentUpdated, }, }, ctx, }); } catch (error) { throw error; } } }