import { ObjectType, Field, ID, ArgsType, InputType, registerEnumType } from 'type-graphql'; import { ApolloError } from 'apollo-server-lambda'; import { BaseGraphModel } from '@seed/graphql/BaseGraphModel'; import { Permission } from '@seed/interfaces/permission'; import { GetArgs } from '@seed/graphql/Request'; import AccountModel from '@src/accounts/account.model'; import { TranslatableComponent } from '@src/__components/components'; import { AccountTypeEnum } from '@src/accounts/account.components'; import { ApolloContext } from '@seed/interfaces/context'; import { PromoType } from './component'; const permissions: Permission = { c: [AccountTypeEnum.admin], r: [AccountTypeEnum.public, AccountTypeEnum.admin], w: [AccountTypeEnum.admin], d: [AccountTypeEnum.admin], }; @ObjectType() export default class PromoModel extends BaseGraphModel { public constructor() { super({ collectionName: 'shop.promos', permissions: permissions, }); } @Field(() => ID) readonly _id: string; @Field() code: string; @Field(() => TranslatableComponent, { nullable: true }) description: TranslatableComponent; @Field(() => PromoType) type: PromoType; @Field() value: number; @Field({ nullable: true }) validity?: Date; @Field() cummulable: boolean; @Field({ nullable: true }) usageLimit?: number; @Field() usage: number; searchOptions(): string[] { return ['code']; } filterOptions(): string[] { return ['code']; } // validatePromo = (): void => { // try { // if (this.usageLimit && this.usageLimit <= this.usage) { // throw new ApolloError('promo.notValid', '404'); // } // if (this.validity) { // const today = new Date(); // if (this.validity < today) throw new ApolloError('promo.expired', '404'); // } // } catch (error) { // throw error; // } // }; } @ArgsType() export class PromoArgs { @Field(() => GetArgs, { nullable: true }) pagination?: GetArgs; @Field({ nullable: true }) search?: string; } @InputType() export class NewPromoInput { @Field() code: string; @Field(() => TranslatableComponent, { nullable: true }) description: TranslatableComponent; @Field(() => PromoType) type: PromoType; @Field() value: number; @Field() cummulable: boolean; @Field({ nullable: true }) validity?: Date; @Field({ nullable: true }) usageLimit?: number; } @InputType() export class EditPromoInput { @Field({ nullable: true }) code: string; @Field(() => TranslatableComponent, { nullable: true }) description: TranslatableComponent; @Field(() => PromoType, { nullable: true }) type: PromoType; @Field({ nullable: true }) value: number; @Field({ nullable: true }) cummulable: boolean; @Field({ nullable: true }) validity?: Date; @Field({ nullable: true }) usageLimit?: number; } export const onCreate = async (input: NewPromoInput, ctx: ApolloContext): Promise => { try { const promo = await (await new PromoModel().db()).findOne({ code: input.code }); if (promo) { throw new ApolloError('promo.nameTaken', '404'); } } catch (error) { throw error; } }; export const onUpdate = async (input: EditPromoInput, ctx: ApolloContext): Promise => { try { const promo = await (await new PromoModel().db()).findOne({ code: input.code }); if (promo) { throw new ApolloError('promo.nameTaken', '404'); } } catch (error) { throw error; } }; export const validatePromo = async (code: string, ctx: ApolloContext): Promise => { try { const promo = await new PromoModel().getOne({ code }, ctx); if (promo.usageLimit && promo.usageLimit <= promo.usage) { throw new ApolloError('promo.notValid', '404'); } if (promo.validity) { const today = new Date(); if (promo.validity < today) throw new ApolloError('promo.expired', '404'); } } catch (error) { throw error; } };