This commit is contained in:
2025-11-21 18:37:09 +03:30
parent e2a04e6a50
commit 2c0ab601f3
22 changed files with 669 additions and 2 deletions
+151
View File
@@ -67,6 +67,7 @@
"supertest": "^7.0.0",
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.2",
"ts-node": "^10.9.2",
"typescript": "^5.7.3",
"typescript-eslint": "^8.20.0"
}
@@ -1957,6 +1958,30 @@
"node": ">=0.1.90"
}
},
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@emnapi/core": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.6.0.tgz",
@@ -5717,6 +5742,34 @@
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
"license": "MIT"
},
"node_modules/@tsconfig/node10": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
"integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true,
"license": "MIT"
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true,
"license": "MIT"
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"dev": true,
"license": "MIT"
},
"node_modules/@tybys/wasm-util": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
@@ -6829,6 +6882,19 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/acorn-walk": {
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
"dev": true,
"license": "MIT",
"dependencies": {
"acorn": "^8.11.0"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -6991,6 +7057,13 @@
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
"license": "MIT"
},
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true,
"license": "MIT"
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -7970,6 +8043,13 @@
}
}
},
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true,
"license": "MIT"
},
"node_modules/cron-parser": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz",
@@ -8175,6 +8255,16 @@
"wrappy": "1"
}
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -14281,6 +14371,50 @@
"webpack": "^5.0.0"
}
},
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"bin": {
"ts-node": "dist/bin.js",
"ts-node-cwd": "dist/bin-cwd.js",
"ts-node-esm": "dist/bin-esm.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js",
"ts-script": "dist/bin-script-deprecated.js"
},
"peerDependencies": {
"@swc/core": ">=1.2.50",
"@swc/wasm": ">=1.2.50",
"@types/node": "*",
"typescript": ">=2.7"
},
"peerDependenciesMeta": {
"@swc/core": {
"optional": true
},
"@swc/wasm": {
"optional": true
}
}
},
"node_modules/tsconfig-paths": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
@@ -14602,6 +14736,13 @@
"uuid": "dist/esm/bin/uuid"
}
},
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true,
"license": "MIT"
},
"node_modules/v8-to-istanbul": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
@@ -15127,6 +15268,16 @@
"node": ">=12"
}
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+2 -1
View File
@@ -7,7 +7,7 @@
"license": "UNLICENSED",
"scripts": {
"db:create": "npx mikro-orm schema:create --run --config ./src/config/mikro-orm.config.dev.ts",
"db:update": "npx mikro-orm schema:update --run --config ./src/config/mikro-orm.config.dev.ts",
"db:update": "npx mikro-orm schema:update --run --config ./src/config/mikro-orm.config.dev.ts ",
"db:drop": "npx mikro-orm schema:drop --run --config ./src/config/mikro-orm.config.dev.ts",
"db:seed": "npx mikro-orm seeder:run --config ./src/config/mikro-orm.config.dev.ts",
"build": "nest build",
@@ -82,6 +82,7 @@
"supertest": "^7.0.0",
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.2",
"ts-node": "^10.9.2",
"typescript": "^5.7.3",
"typescript-eslint": "^8.20.0"
},
+2
View File
@@ -20,6 +20,7 @@ import { CartModule } from './modules/cart/cart.module';
import { RolesModule } from './modules/roles/roles.module';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { PaymentsModule } from './modules/payments/payments.module';
@Module({
imports: [
@@ -58,6 +59,7 @@ import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
FoodModule,
CartModule,
RolesModule,
PaymentsModule,
],
controllers: [],
providers: [],
-1
View File
@@ -11,7 +11,6 @@ export class HttpExceptionFilter implements ExceptionFilter {
// In GraphQL context, host is actually an ExecutionContext
const gqlContext = GqlExecutionContext.create(host as ExecutionContext);
if (gqlContext && gqlContext.getInfo()) {
console.log('GraphQL context**');
// For GraphQL, let the exception propagate - GraphQL will handle it automatically
// We can't use HTTP response methods in GraphQL context
return;
@@ -0,0 +1,19 @@
import { InputType, Field, Int } from '@nestjs/graphql';
@InputType()
export class CreatePaymentMethodInput {
@Field()
name!: string;
@Field({ nullable: true })
description?: string;
@Field({ nullable: true })
icon?: string;
@Field(() => Boolean, { nullable: true, defaultValue: true })
isActive?: boolean;
@Field(() => Int, { nullable: true })
order?: number;
}
@@ -0,0 +1,7 @@
import { InputType, Int, Field } from '@nestjs/graphql';
@InputType()
export class CreatePaymentInput {
@Field(() => Int, { description: 'Example field (placeholder)' })
exampleField: number;
}
@@ -0,0 +1,16 @@
import { InputType, Field } from '@nestjs/graphql';
@InputType()
export class CreateRestaurantPaymentMethodInput {
@Field()
restaurantId!: string;
@Field()
paymentMethodId!: string;
@Field({ nullable: true })
merchantId?: string;
@Field({ nullable: true })
isActive?: boolean;
}
@@ -0,0 +1,8 @@
import { CreatePaymentMethodInput } from './create-payment-method.input';
import { InputType, Field, PartialType } from '@nestjs/graphql';
@InputType()
export class UpdatePaymentMethodInput extends PartialType(CreatePaymentMethodInput) {
@Field()
id!: string;
}
@@ -0,0 +1,8 @@
import { CreatePaymentInput } from './create-payment.input';
import { InputType, Field, Int, PartialType } from '@nestjs/graphql';
@InputType()
export class UpdatePaymentInput extends PartialType(CreatePaymentInput) {
@Field(() => Int)
id: number;
}
@@ -0,0 +1,8 @@
import { CreateRestaurantPaymentMethodInput } from './create-restaurant-payment-method.input';
import { InputType, Field, PartialType } from '@nestjs/graphql';
@InputType()
export class UpdateRestaurantPaymentMethodInput extends PartialType(CreateRestaurantPaymentMethodInput) {
@Field()
id!: string;
}
@@ -0,0 +1,31 @@
import { Entity, Property } from '@mikro-orm/core';
import { BaseEntity } from '../../../common/entities/base.entity';
import { ObjectType, Field, Int } from '@nestjs/graphql';
@ObjectType()
@Entity({ tableName: 'payment_methods' })
export class PaymentMethod extends BaseEntity {
@Field()
@Property()
name!: string;
@Field()
@Property()
keyName!: string;
@Field({ nullable: true })
@Property({ nullable: true })
description?: string;
@Field({ nullable: true })
@Property({ nullable: true })
icon?: string;
@Field(() => Boolean)
@Property({ default: true })
isActive: boolean = true;
@Field(() => Int, { nullable: true })
@Property({ type: 'int', nullable: true })
order?: number;
}
@@ -0,0 +1,7 @@
import { ObjectType, Field, Int } from '@nestjs/graphql';
@ObjectType()
export class Payment {
@Field(() => Int, { description: 'Example field (placeholder)' })
exampleField: number;
}
@@ -0,0 +1,26 @@
import { Entity, ManyToOne, Unique, Property } from '@mikro-orm/core';
import { BaseEntity } from '../../../common/entities/base.entity';
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
import { PaymentMethod } from './payment-method.entity';
import { ObjectType, Field } from '@nestjs/graphql';
@ObjectType()
@Entity({ tableName: 'restaurant_payment_methods' })
@Unique({ properties: ['restaurant', 'paymentMethod'] })
export class RestaurantPaymentMethod extends BaseEntity {
@ManyToOne(() => Restaurant)
restaurant!: Restaurant;
@Field(() => PaymentMethod, { nullable: true })
@ManyToOne(() => PaymentMethod)
paymentMethod!: PaymentMethod;
// Add merchant ID for payment gateway providers (e.g., ZarinPal)
@Field({ nullable: true })
@Property({ nullable: true })
merchantId?: string;
@Field({ nullable: true })
@Property({ type: 'boolean', default: true })
isActive: boolean = true;
}
+34
View File
@@ -0,0 +1,34 @@
import { Module } from '@nestjs/common';
import { PaymentsService } from './services/payments.service';
import { PaymentsResolver } from './resolvers/payments.resolver';
import { MikroOrmModule } from '@mikro-orm/nestjs';
import { PaymentMethod } from './entities/payment-method.entity';
import { PaymentMethodRepository } from './repositories/payment-method.repository';
import { PaymentMethodService } from './services/payment-method.service';
import { PaymentMethodResolver } from './resolvers/payment-method.resolver';
import { RestaurantPaymentMethod } from './entities/restaurant-payment-method.entity';
import { RestaurantPaymentMethodRepository } from './repositories/restaurant-payment-method.repository';
import { RestaurantPaymentMethodService } from './services/restaurant-payment-method.service';
import { RestaurantPaymentMethodResolver } from './resolvers/restaurant-payment-method.resolver';
import { Restaurant } from '../restaurants/entities/restaurant.entity';
@Module({
imports: [MikroOrmModule.forFeature([PaymentMethod, RestaurantPaymentMethod, Restaurant])],
providers: [
PaymentsResolver,
PaymentsService,
PaymentMethodResolver,
PaymentMethodService,
PaymentMethodRepository,
RestaurantPaymentMethodResolver,
RestaurantPaymentMethodService,
RestaurantPaymentMethodRepository,
],
exports: [
PaymentMethodRepository,
PaymentMethodService,
RestaurantPaymentMethodRepository,
RestaurantPaymentMethodService,
],
})
export class PaymentsModule {}
@@ -0,0 +1,10 @@
import { Injectable } from '@nestjs/common';
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
import { PaymentMethod } from '../entities/payment-method.entity';
@Injectable()
export class PaymentMethodRepository extends EntityRepository<PaymentMethod> {
constructor(readonly em: EntityManager) {
super(em, PaymentMethod);
}
}
@@ -0,0 +1,10 @@
import { Injectable } from '@nestjs/common';
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
import { RestaurantPaymentMethod } from '../entities/restaurant-payment-method.entity';
@Injectable()
export class RestaurantPaymentMethodRepository extends EntityRepository<RestaurantPaymentMethod> {
constructor(readonly em: EntityManager) {
super(em, RestaurantPaymentMethod);
}
}
@@ -0,0 +1,35 @@
import { Resolver, Query, Mutation, Args, ID } from '@nestjs/graphql';
import { PaymentMethodService } from '../services/payment-method.service';
import { PaymentMethod } from '../entities/payment-method.entity';
import { CreatePaymentMethodInput } from '../dto/create-payment-method.input';
import { UpdatePaymentMethodInput } from '../dto/update-payment-method.input';
@Resolver(() => PaymentMethod)
export class PaymentMethodResolver {
constructor(private readonly paymentMethodService: PaymentMethodService) {}
@Mutation(() => PaymentMethod)
createPaymentMethod(@Args('createPaymentMethodInput') createPaymentMethodInput: CreatePaymentMethodInput) {
return this.paymentMethodService.create(createPaymentMethodInput);
}
@Query(() => [PaymentMethod], { name: 'paymentMethods' })
findAll() {
return this.paymentMethodService.findAll();
}
@Query(() => PaymentMethod, { name: 'paymentMethod' })
findOne(@Args('id', { type: () => ID }) id: string) {
return this.paymentMethodService.findOne(id);
}
@Mutation(() => PaymentMethod)
updatePaymentMethod(@Args('updatePaymentMethodInput') updatePaymentMethodInput: UpdatePaymentMethodInput) {
return this.paymentMethodService.update(updatePaymentMethodInput.id, updatePaymentMethodInput);
}
@Mutation(() => PaymentMethod)
removePaymentMethod(@Args('id', { type: () => ID }) id: string) {
return this.paymentMethodService.remove(id);
}
}
@@ -0,0 +1,35 @@
import { Resolver, Query, Mutation, Args, Int } from '@nestjs/graphql';
import { PaymentsService } from '../services/payments.service';
import { Payment } from '../entities/payment.entity';
import { CreatePaymentInput } from '../dto/create-payment.input';
import { UpdatePaymentInput } from '../dto/update-payment.input';
@Resolver(() => Payment)
export class PaymentsResolver {
constructor(private readonly paymentsService: PaymentsService) {}
@Mutation(() => Payment)
createPayment(@Args('createPaymentInput') createPaymentInput: CreatePaymentInput) {
return this.paymentsService.create(createPaymentInput);
}
@Query(() => [Payment], { name: 'payments' })
findAll() {
return this.paymentsService.findAll();
}
@Query(() => Payment, { name: 'payment' })
findOne(@Args('id', { type: () => Int }) id: number) {
return this.paymentsService.findOne(id);
}
@Mutation(() => Payment)
updatePayment(@Args('updatePaymentInput') updatePaymentInput: UpdatePaymentInput) {
return this.paymentsService.update(updatePaymentInput.id, updatePaymentInput);
}
@Mutation(() => Payment)
removePayment(@Args('id', { type: () => Int }) id: number) {
return this.paymentsService.remove(id);
}
}
@@ -0,0 +1,52 @@
import { Resolver, Query, Mutation, Args, ID } from '@nestjs/graphql';
import { RestaurantPaymentMethodService } from '../services/restaurant-payment-method.service';
import { RestaurantPaymentMethod } from '../entities/restaurant-payment-method.entity';
import { CreateRestaurantPaymentMethodInput } from '../dto/create-restaurant-payment-method.input';
import { UpdateRestaurantPaymentMethodInput } from '../dto/update-restaurant-payment-method.input';
@Resolver(() => RestaurantPaymentMethod)
export class RestaurantPaymentMethodResolver {
constructor(private readonly restaurantPaymentMethodService: RestaurantPaymentMethodService) {}
@Mutation(() => RestaurantPaymentMethod)
createRestaurantPaymentMethod(
@Args('createRestaurantPaymentMethodInput') createRestaurantPaymentMethodInput: CreateRestaurantPaymentMethodInput,
) {
return this.restaurantPaymentMethodService.create(createRestaurantPaymentMethodInput);
}
@Query(() => [RestaurantPaymentMethod], { name: 'restaurantPaymentMethods' })
findAll() {
return this.restaurantPaymentMethodService.findAll();
}
@Query(() => [RestaurantPaymentMethod], { name: 'restaurantPaymentMethodsByRestaurant' })
findByRestaurant(@Args('restaurantId', { type: () => ID }) restaurantId: string) {
return this.restaurantPaymentMethodService.findByRestaurant(restaurantId);
}
@Query(() => [RestaurantPaymentMethod], { name: 'restaurantPaymentMethodsByPaymentMethod' })
findByPaymentMethod(@Args('paymentMethodId', { type: () => ID }) paymentMethodId: string) {
return this.restaurantPaymentMethodService.findByPaymentMethod(paymentMethodId);
}
@Query(() => RestaurantPaymentMethod, { name: 'restaurantPaymentMethod' })
findOne(@Args('id', { type: () => ID }) id: string) {
return this.restaurantPaymentMethodService.findOne(id);
}
@Mutation(() => RestaurantPaymentMethod)
updateRestaurantPaymentMethod(
@Args('updateRestaurantPaymentMethodInput') updateRestaurantPaymentMethodInput: UpdateRestaurantPaymentMethodInput,
) {
return this.restaurantPaymentMethodService.update(
updateRestaurantPaymentMethodInput.id,
updateRestaurantPaymentMethodInput,
);
}
@Mutation(() => RestaurantPaymentMethod)
removeRestaurantPaymentMethod(@Args('id', { type: () => ID }) id: string) {
return this.restaurantPaymentMethodService.remove(id);
}
}
@@ -0,0 +1,48 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { EntityManager } from '@mikro-orm/postgresql';
import { PaymentMethod } from '../entities/payment-method.entity';
import { PaymentMethodRepository } from '../repositories/payment-method.repository';
import { CreatePaymentMethodInput } from '../dto/create-payment-method.input';
import { UpdatePaymentMethodInput } from '../dto/update-payment-method.input';
import { RequiredEntityData } from '@mikro-orm/core';
@Injectable()
export class PaymentMethodService {
constructor(
private readonly paymentMethodRepository: PaymentMethodRepository,
private readonly em: EntityManager,
) {}
async create(createPaymentMethodInput: CreatePaymentMethodInput): Promise<PaymentMethod> {
const paymentMethod = this.paymentMethodRepository.create(
createPaymentMethodInput as unknown as RequiredEntityData<PaymentMethod>,
);
await this.em.persistAndFlush(paymentMethod);
return paymentMethod;
}
async findAll(): Promise<PaymentMethod[]> {
return this.paymentMethodRepository.findAll();
}
async findOne(id: string): Promise<PaymentMethod> {
const paymentMethod = await this.paymentMethodRepository.findOne({ id });
if (!paymentMethod) {
throw new NotFoundException(`PaymentMethod with ID ${id} not found`);
}
return paymentMethod;
}
async update(id: string, updatePaymentMethodInput: UpdatePaymentMethodInput): Promise<PaymentMethod> {
const paymentMethod = await this.findOne(id);
this.em.assign(paymentMethod, updatePaymentMethodInput);
await this.em.flush();
return paymentMethod;
}
async remove(id: string): Promise<PaymentMethod> {
const paymentMethod = await this.findOne(id);
await this.em.removeAndFlush(paymentMethod);
return paymentMethod;
}
}
@@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common';
import { CreatePaymentInput } from '../dto/create-payment.input';
import { UpdatePaymentInput } from '../dto/update-payment.input';
@Injectable()
export class PaymentsService {
create(createPaymentInput: CreatePaymentInput) {
return 'This action adds a new payment';
}
findAll() {
return `This action returns all payments`;
}
findOne(id: number) {
return `This action returns a #${id} payment`;
}
update(id: number, updatePaymentInput: UpdatePaymentInput) {
return `This action updates a #${id} payment`;
}
remove(id: number) {
return `This action removes a #${id} payment`;
}
}
@@ -0,0 +1,134 @@
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
import { EntityManager } from '@mikro-orm/postgresql';
import { RestaurantPaymentMethod } from '../entities/restaurant-payment-method.entity';
import { RestaurantPaymentMethodRepository } from '../repositories/restaurant-payment-method.repository';
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
import { PaymentMethod } from '../entities/payment-method.entity';
import { CreateRestaurantPaymentMethodInput } from '../dto/create-restaurant-payment-method.input';
import { UpdateRestaurantPaymentMethodInput } from '../dto/update-restaurant-payment-method.input';
import { RequiredEntityData } from '@mikro-orm/core';
@Injectable()
export class RestaurantPaymentMethodService {
constructor(
private readonly restaurantPaymentMethodRepository: RestaurantPaymentMethodRepository,
private readonly em: EntityManager,
) {}
async create(
createRestaurantPaymentMethodInput: CreateRestaurantPaymentMethodInput,
): Promise<RestaurantPaymentMethod> {
// Check if restaurant exists
const restaurant = await this.em.findOne(Restaurant, { id: createRestaurantPaymentMethodInput.restaurantId });
if (!restaurant) {
throw new NotFoundException(`Restaurant with ID ${createRestaurantPaymentMethodInput.restaurantId} not found`);
}
// Check if payment method exists
const paymentMethod = await this.em.findOne(PaymentMethod, { id: createRestaurantPaymentMethodInput.paymentMethodId });
if (!paymentMethod) {
throw new NotFoundException(`PaymentMethod with ID ${createRestaurantPaymentMethodInput.paymentMethodId} not found`);
}
// Check if the relationship already exists
const existing = await this.restaurantPaymentMethodRepository.findOne({
restaurant: { id: createRestaurantPaymentMethodInput.restaurantId },
paymentMethod: { id: createRestaurantPaymentMethodInput.paymentMethodId },
});
if (existing) {
throw new ConflictException('This payment method is already assigned to this restaurant');
}
const restaurantPaymentMethod = this.restaurantPaymentMethodRepository.create({
restaurant,
paymentMethod,
merchantId: createRestaurantPaymentMethodInput.merchantId,
isActive: createRestaurantPaymentMethodInput.isActive ?? true,
} as unknown as RequiredEntityData<RestaurantPaymentMethod>);
await this.em.persistAndFlush(restaurantPaymentMethod);
return restaurantPaymentMethod;
}
async findAll(): Promise<RestaurantPaymentMethod[]> {
return this.restaurantPaymentMethodRepository.findAll({ populate: ['restaurant', 'paymentMethod'] });
}
async findByRestaurant(restaurantId: string): Promise<RestaurantPaymentMethod[]> {
return this.restaurantPaymentMethodRepository.find(
{ restaurant: { id: restaurantId } },
{ populate: ['restaurant', 'paymentMethod'] },
);
}
async findByPaymentMethod(paymentMethodId: string): Promise<RestaurantPaymentMethod[]> {
return this.restaurantPaymentMethodRepository.find(
{ paymentMethod: { id: paymentMethodId } },
{ populate: ['restaurant', 'paymentMethod'] },
);
}
async findOne(id: string): Promise<RestaurantPaymentMethod> {
const restaurantPaymentMethod = await this.restaurantPaymentMethodRepository.findOne(
{ id },
{ populate: ['restaurant', 'paymentMethod'] },
);
if (!restaurantPaymentMethod) {
throw new NotFoundException(`RestaurantPaymentMethod with ID ${id} not found`);
}
return restaurantPaymentMethod;
}
async update(
id: string,
updateRestaurantPaymentMethodInput: UpdateRestaurantPaymentMethodInput,
): Promise<RestaurantPaymentMethod> {
const restaurantPaymentMethod = await this.findOne(id);
if (updateRestaurantPaymentMethodInput.restaurantId) {
const restaurant = await this.em.findOne(Restaurant, { id: updateRestaurantPaymentMethodInput.restaurantId });
if (!restaurant) {
throw new NotFoundException(`Restaurant with ID ${updateRestaurantPaymentMethodInput.restaurantId} not found`);
}
restaurantPaymentMethod.restaurant = restaurant;
}
if (updateRestaurantPaymentMethodInput.paymentMethodId) {
const paymentMethod = await this.em.findOne(PaymentMethod, { id: updateRestaurantPaymentMethodInput.paymentMethodId });
if (!paymentMethod) {
throw new NotFoundException(`PaymentMethod with ID ${updateRestaurantPaymentMethodInput.paymentMethodId} not found`);
}
// Check if the new relationship already exists
const existing = await this.restaurantPaymentMethodRepository.findOne({
restaurant: { id: restaurantPaymentMethod.restaurant.id },
paymentMethod: { id: updateRestaurantPaymentMethodInput.paymentMethodId },
});
if (existing && existing.id !== id) {
throw new ConflictException('This payment method is already assigned to this restaurant');
}
restaurantPaymentMethod.paymentMethod = paymentMethod;
}
// Update merchantId and isActive if provided
if (updateRestaurantPaymentMethodInput.merchantId !== undefined) {
restaurantPaymentMethod.merchantId = updateRestaurantPaymentMethodInput.merchantId;
}
if (updateRestaurantPaymentMethodInput.isActive !== undefined) {
restaurantPaymentMethod.isActive = updateRestaurantPaymentMethodInput.isActive;
}
await this.em.flush();
return restaurantPaymentMethod;
}
async remove(id: string): Promise<RestaurantPaymentMethod> {
const restaurantPaymentMethod = await this.findOne(id);
await this.em.removeAndFlush(restaurantPaymentMethod);
return restaurantPaymentMethod;
}
}