2025-05-14 21:45:16 +02:00

172 lines
4.2 KiB
TypeScript

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<void> => {
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<void> => {
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<void> => {
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;
}
};