Просмотр исходного кода

feat(core): Add channel mutations for ShippingMethod & PaymentMethod

Michael Bromley 2 лет назад
Родитель
Сommit
58788801dd

+ 48 - 0
packages/asset-server-plugin/e2e/graphql/generated-e2e-asset-server-plugin-types.ts

@@ -242,6 +242,11 @@ export type AssignFacetsToChannelInput = {
   facetIds: Array<Scalars['ID']>;
 };
 
+export type AssignPaymentMethodsToChannelInput = {
+  channelId: Scalars['ID'];
+  paymentMethodIds: Array<Scalars['ID']>;
+};
+
 export type AssignProductVariantsToChannelInput = {
   channelId: Scalars['ID'];
   priceFactor?: InputMaybe<Scalars['Float']>;
@@ -259,6 +264,11 @@ export type AssignPromotionsToChannelInput = {
   promotionIds: Array<Scalars['ID']>;
 };
 
+export type AssignShippingMethodsToChannelInput = {
+  channelId: Scalars['ID'];
+  shippingMethodIds: Array<Scalars['ID']>;
+};
+
 export type AssignStockLocationsToChannelInput = {
   channelId: Scalars['ID'];
   stockLocationIds: Array<Scalars['ID']>;
@@ -2484,6 +2494,8 @@ export type Mutation = {
   assignCollectionsToChannel: Array<Collection>;
   /** Assigns Facets to the specified Channel */
   assignFacetsToChannel: Array<Facet>;
+  /** Assigns PaymentMethods to the specified Channel */
+  assignPaymentMethodsToChannel: Array<PaymentMethod>;
   /** Assigns ProductVariants to the specified Channel */
   assignProductVariantsToChannel: Array<ProductVariant>;
   /** Assigns all ProductVariants of Product to the specified Channel */
@@ -2492,6 +2504,8 @@ export type Mutation = {
   assignPromotionsToChannel: Array<Promotion>;
   /** Assign a Role to an Administrator */
   assignRoleToAdministrator: Administrator;
+  /** Assigns ShippingMethods to the specified Channel */
+  assignShippingMethodsToChannel: Array<ShippingMethod>;
   /** Assigns StockLocations to the specified Channel */
   assignStockLocationsToChannel: Array<StockLocation>;
   /** Authenticates the user using a named authentication strategy */
@@ -2668,6 +2682,8 @@ export type Mutation = {
    * as well as removing any of the group's options from the Product's ProductVariants.
    */
   removeOptionGroupFromProduct: RemoveOptionGroupFromProductResult;
+  /** Removes PaymentMethods from the specified Channel */
+  removePaymentMethodsFromChannel: Array<PaymentMethod>;
   /** Removes ProductVariants from the specified Channel */
   removeProductVariantsFromChannel: Array<ProductVariant>;
   /** Removes all ProductVariants of Product from the specified Channel */
@@ -2676,6 +2692,8 @@ export type Mutation = {
   removePromotionsFromChannel: Array<Promotion>;
   /** Remove all settled jobs in the given queues older than the given date. Returns the number of jobs deleted. */
   removeSettledJobs: Scalars['Int'];
+  /** Removes ShippingMethods from the specified Channel */
+  removeShippingMethodsFromChannel: Array<ShippingMethod>;
   /** Removes StockLocations from the specified Channel */
   removeStockLocationsFromChannel: Array<StockLocation>;
   runPendingSearchIndexUpdates: Success;
@@ -2823,6 +2841,11 @@ export type MutationAssignFacetsToChannelArgs = {
 };
 
 
+export type MutationAssignPaymentMethodsToChannelArgs = {
+  input: AssignPaymentMethodsToChannelInput;
+};
+
+
 export type MutationAssignProductVariantsToChannelArgs = {
   input: AssignProductVariantsToChannelInput;
 };
@@ -2844,6 +2867,11 @@ export type MutationAssignRoleToAdministratorArgs = {
 };
 
 
+export type MutationAssignShippingMethodsToChannelArgs = {
+  input: AssignShippingMethodsToChannelInput;
+};
+
+
 export type MutationAssignStockLocationsToChannelArgs = {
   input: AssignStockLocationsToChannelInput;
 };
@@ -3305,6 +3333,11 @@ export type MutationRemoveOptionGroupFromProductArgs = {
 };
 
 
+export type MutationRemovePaymentMethodsFromChannelArgs = {
+  input: RemovePaymentMethodsFromChannelInput;
+};
+
+
 export type MutationRemoveProductVariantsFromChannelArgs = {
   input: RemoveProductVariantsFromChannelInput;
 };
@@ -3326,6 +3359,11 @@ export type MutationRemoveSettledJobsArgs = {
 };
 
 
+export type MutationRemoveShippingMethodsFromChannelArgs = {
+  input: RemoveShippingMethodsFromChannelInput;
+};
+
+
 export type MutationRemoveStockLocationsFromChannelArgs = {
   input: RemoveStockLocationsFromChannelInput;
 };
@@ -5185,6 +5223,11 @@ export type RemoveOptionGroupFromProductResult = Product | ProductOptionInUseErr
 
 export type RemoveOrderItemsResult = Order | OrderModificationError;
 
+export type RemovePaymentMethodsFromChannelInput = {
+  channelId: Scalars['ID'];
+  paymentMethodIds: Array<Scalars['ID']>;
+};
+
 export type RemoveProductVariantsFromChannelInput = {
   channelId: Scalars['ID'];
   productVariantIds: Array<Scalars['ID']>;
@@ -5200,6 +5243,11 @@ export type RemovePromotionsFromChannelInput = {
   promotionIds: Array<Scalars['ID']>;
 };
 
+export type RemoveShippingMethodsFromChannelInput = {
+  channelId: Scalars['ID'];
+  shippingMethodIds: Array<Scalars['ID']>;
+};
+
 export type RemoveStockLocationsFromChannelInput = {
   channelId: Scalars['ID'];
   stockLocationIds: Array<Scalars['ID']>;

+ 48 - 0
packages/common/src/generated-types.ts

@@ -249,6 +249,11 @@ export type AssignFacetsToChannelInput = {
   facetIds: Array<Scalars['ID']>;
 };
 
+export type AssignPaymentMethodsToChannelInput = {
+  channelId: Scalars['ID'];
+  paymentMethodIds: Array<Scalars['ID']>;
+};
+
 export type AssignProductVariantsToChannelInput = {
   channelId: Scalars['ID'];
   priceFactor?: InputMaybe<Scalars['Float']>;
@@ -266,6 +271,11 @@ export type AssignPromotionsToChannelInput = {
   promotionIds: Array<Scalars['ID']>;
 };
 
+export type AssignShippingMethodsToChannelInput = {
+  channelId: Scalars['ID'];
+  shippingMethodIds: Array<Scalars['ID']>;
+};
+
 export type AssignStockLocationsToChannelInput = {
   channelId: Scalars['ID'];
   stockLocationIds: Array<Scalars['ID']>;
@@ -2566,6 +2576,8 @@ export type Mutation = {
   assignCollectionsToChannel: Array<Collection>;
   /** Assigns Facets to the specified Channel */
   assignFacetsToChannel: Array<Facet>;
+  /** Assigns PaymentMethods to the specified Channel */
+  assignPaymentMethodsToChannel: Array<PaymentMethod>;
   /** Assigns ProductVariants to the specified Channel */
   assignProductVariantsToChannel: Array<ProductVariant>;
   /** Assigns all ProductVariants of Product to the specified Channel */
@@ -2574,6 +2586,8 @@ export type Mutation = {
   assignPromotionsToChannel: Array<Promotion>;
   /** Assign a Role to an Administrator */
   assignRoleToAdministrator: Administrator;
+  /** Assigns ShippingMethods to the specified Channel */
+  assignShippingMethodsToChannel: Array<ShippingMethod>;
   /** Assigns StockLocations to the specified Channel */
   assignStockLocationsToChannel: Array<StockLocation>;
   /** Authenticates the user using a named authentication strategy */
@@ -2750,6 +2764,8 @@ export type Mutation = {
    * as well as removing any of the group's options from the Product's ProductVariants.
    */
   removeOptionGroupFromProduct: RemoveOptionGroupFromProductResult;
+  /** Removes PaymentMethods from the specified Channel */
+  removePaymentMethodsFromChannel: Array<PaymentMethod>;
   /** Removes ProductVariants from the specified Channel */
   removeProductVariantsFromChannel: Array<ProductVariant>;
   /** Removes all ProductVariants of Product from the specified Channel */
@@ -2758,6 +2774,8 @@ export type Mutation = {
   removePromotionsFromChannel: Array<Promotion>;
   /** Remove all settled jobs in the given queues older than the given date. Returns the number of jobs deleted. */
   removeSettledJobs: Scalars['Int'];
+  /** Removes ShippingMethods from the specified Channel */
+  removeShippingMethodsFromChannel: Array<ShippingMethod>;
   /** Removes StockLocations from the specified Channel */
   removeStockLocationsFromChannel: Array<StockLocation>;
   runPendingSearchIndexUpdates: Success;
@@ -2905,6 +2923,11 @@ export type MutationAssignFacetsToChannelArgs = {
 };
 
 
+export type MutationAssignPaymentMethodsToChannelArgs = {
+  input: AssignPaymentMethodsToChannelInput;
+};
+
+
 export type MutationAssignProductVariantsToChannelArgs = {
   input: AssignProductVariantsToChannelInput;
 };
@@ -2926,6 +2949,11 @@ export type MutationAssignRoleToAdministratorArgs = {
 };
 
 
+export type MutationAssignShippingMethodsToChannelArgs = {
+  input: AssignShippingMethodsToChannelInput;
+};
+
+
 export type MutationAssignStockLocationsToChannelArgs = {
   input: AssignStockLocationsToChannelInput;
 };
@@ -3387,6 +3415,11 @@ export type MutationRemoveOptionGroupFromProductArgs = {
 };
 
 
+export type MutationRemovePaymentMethodsFromChannelArgs = {
+  input: RemovePaymentMethodsFromChannelInput;
+};
+
+
 export type MutationRemoveProductVariantsFromChannelArgs = {
   input: RemoveProductVariantsFromChannelInput;
 };
@@ -3408,6 +3441,11 @@ export type MutationRemoveSettledJobsArgs = {
 };
 
 
+export type MutationRemoveShippingMethodsFromChannelArgs = {
+  input: RemoveShippingMethodsFromChannelInput;
+};
+
+
 export type MutationRemoveStockLocationsFromChannelArgs = {
   input: RemoveStockLocationsFromChannelInput;
 };
@@ -5321,6 +5359,11 @@ export type RemoveOptionGroupFromProductResult = Product | ProductOptionInUseErr
 
 export type RemoveOrderItemsResult = Order | OrderModificationError;
 
+export type RemovePaymentMethodsFromChannelInput = {
+  channelId: Scalars['ID'];
+  paymentMethodIds: Array<Scalars['ID']>;
+};
+
 export type RemoveProductVariantsFromChannelInput = {
   channelId: Scalars['ID'];
   productVariantIds: Array<Scalars['ID']>;
@@ -5336,6 +5379,11 @@ export type RemovePromotionsFromChannelInput = {
   promotionIds: Array<Scalars['ID']>;
 };
 
+export type RemoveShippingMethodsFromChannelInput = {
+  channelId: Scalars['ID'];
+  shippingMethodIds: Array<Scalars['ID']>;
+};
+
 export type RemoveStockLocationsFromChannelInput = {
   channelId: Scalars['ID'];
   stockLocationIds: Array<Scalars['ID']>;

+ 48 - 0
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -242,6 +242,11 @@ export type AssignFacetsToChannelInput = {
   facetIds: Array<Scalars['ID']>;
 };
 
+export type AssignPaymentMethodsToChannelInput = {
+  channelId: Scalars['ID'];
+  paymentMethodIds: Array<Scalars['ID']>;
+};
+
 export type AssignProductVariantsToChannelInput = {
   channelId: Scalars['ID'];
   priceFactor?: InputMaybe<Scalars['Float']>;
@@ -259,6 +264,11 @@ export type AssignPromotionsToChannelInput = {
   promotionIds: Array<Scalars['ID']>;
 };
 
+export type AssignShippingMethodsToChannelInput = {
+  channelId: Scalars['ID'];
+  shippingMethodIds: Array<Scalars['ID']>;
+};
+
 export type AssignStockLocationsToChannelInput = {
   channelId: Scalars['ID'];
   stockLocationIds: Array<Scalars['ID']>;
@@ -2484,6 +2494,8 @@ export type Mutation = {
   assignCollectionsToChannel: Array<Collection>;
   /** Assigns Facets to the specified Channel */
   assignFacetsToChannel: Array<Facet>;
+  /** Assigns PaymentMethods to the specified Channel */
+  assignPaymentMethodsToChannel: Array<PaymentMethod>;
   /** Assigns ProductVariants to the specified Channel */
   assignProductVariantsToChannel: Array<ProductVariant>;
   /** Assigns all ProductVariants of Product to the specified Channel */
@@ -2492,6 +2504,8 @@ export type Mutation = {
   assignPromotionsToChannel: Array<Promotion>;
   /** Assign a Role to an Administrator */
   assignRoleToAdministrator: Administrator;
+  /** Assigns ShippingMethods to the specified Channel */
+  assignShippingMethodsToChannel: Array<ShippingMethod>;
   /** Assigns StockLocations to the specified Channel */
   assignStockLocationsToChannel: Array<StockLocation>;
   /** Authenticates the user using a named authentication strategy */
@@ -2668,6 +2682,8 @@ export type Mutation = {
    * as well as removing any of the group's options from the Product's ProductVariants.
    */
   removeOptionGroupFromProduct: RemoveOptionGroupFromProductResult;
+  /** Removes PaymentMethods from the specified Channel */
+  removePaymentMethodsFromChannel: Array<PaymentMethod>;
   /** Removes ProductVariants from the specified Channel */
   removeProductVariantsFromChannel: Array<ProductVariant>;
   /** Removes all ProductVariants of Product from the specified Channel */
@@ -2676,6 +2692,8 @@ export type Mutation = {
   removePromotionsFromChannel: Array<Promotion>;
   /** Remove all settled jobs in the given queues older than the given date. Returns the number of jobs deleted. */
   removeSettledJobs: Scalars['Int'];
+  /** Removes ShippingMethods from the specified Channel */
+  removeShippingMethodsFromChannel: Array<ShippingMethod>;
   /** Removes StockLocations from the specified Channel */
   removeStockLocationsFromChannel: Array<StockLocation>;
   runPendingSearchIndexUpdates: Success;
@@ -2823,6 +2841,11 @@ export type MutationAssignFacetsToChannelArgs = {
 };
 
 
+export type MutationAssignPaymentMethodsToChannelArgs = {
+  input: AssignPaymentMethodsToChannelInput;
+};
+
+
 export type MutationAssignProductVariantsToChannelArgs = {
   input: AssignProductVariantsToChannelInput;
 };
@@ -2844,6 +2867,11 @@ export type MutationAssignRoleToAdministratorArgs = {
 };
 
 
+export type MutationAssignShippingMethodsToChannelArgs = {
+  input: AssignShippingMethodsToChannelInput;
+};
+
+
 export type MutationAssignStockLocationsToChannelArgs = {
   input: AssignStockLocationsToChannelInput;
 };
@@ -3305,6 +3333,11 @@ export type MutationRemoveOptionGroupFromProductArgs = {
 };
 
 
+export type MutationRemovePaymentMethodsFromChannelArgs = {
+  input: RemovePaymentMethodsFromChannelInput;
+};
+
+
 export type MutationRemoveProductVariantsFromChannelArgs = {
   input: RemoveProductVariantsFromChannelInput;
 };
@@ -3326,6 +3359,11 @@ export type MutationRemoveSettledJobsArgs = {
 };
 
 
+export type MutationRemoveShippingMethodsFromChannelArgs = {
+  input: RemoveShippingMethodsFromChannelInput;
+};
+
+
 export type MutationRemoveStockLocationsFromChannelArgs = {
   input: RemoveStockLocationsFromChannelInput;
 };
@@ -5185,6 +5223,11 @@ export type RemoveOptionGroupFromProductResult = Product | ProductOptionInUseErr
 
 export type RemoveOrderItemsResult = Order | OrderModificationError;
 
+export type RemovePaymentMethodsFromChannelInput = {
+  channelId: Scalars['ID'];
+  paymentMethodIds: Array<Scalars['ID']>;
+};
+
 export type RemoveProductVariantsFromChannelInput = {
   channelId: Scalars['ID'];
   productVariantIds: Array<Scalars['ID']>;
@@ -5200,6 +5243,11 @@ export type RemovePromotionsFromChannelInput = {
   promotionIds: Array<Scalars['ID']>;
 };
 
+export type RemoveShippingMethodsFromChannelInput = {
+  channelId: Scalars['ID'];
+  shippingMethodIds: Array<Scalars['ID']>;
+};
+
 export type RemoveStockLocationsFromChannelInput = {
   channelId: Scalars['ID'];
   stockLocationIds: Array<Scalars['ID']>;

+ 23 - 0
packages/core/src/api/resolvers/admin/payment-method.resolver.ts

@@ -2,15 +2,18 @@ import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
 import {
     ConfigurableOperationDefinition,
     DeletionResponse,
+    MutationAssignPaymentMethodsToChannelArgs,
     MutationCreatePaymentMethodArgs,
     MutationDeletePaymentMethodArgs,
     MutationDeletePaymentMethodsArgs,
+    MutationRemovePaymentMethodsFromChannelArgs,
     MutationUpdatePaymentMethodArgs,
     Permission,
     QueryPaymentMethodArgs,
     QueryPaymentMethodsArgs,
 } from '@vendure/common/lib/generated-types';
 import { PaginatedList } from '@vendure/common/lib/shared-types';
+import { Translated } from '../../../common/index';
 
 import { PaymentMethod } from '../../../entity/payment-method/payment-method.entity';
 import { PaymentMethodService } from '../../../service/services/payment-method.service';
@@ -95,4 +98,24 @@ export class PaymentMethodResolver {
     paymentMethodEligibilityCheckers(@Ctx() ctx: RequestContext): ConfigurableOperationDefinition[] {
         return this.paymentMethodService.getPaymentMethodEligibilityCheckers(ctx);
     }
+
+    @Transaction()
+    @Mutation()
+    @Allow(Permission.UpdateSettings, Permission.UpdatePaymentMethod)
+    async assignPaymentMethodsToChannel(
+        @Ctx() ctx: RequestContext,
+        @Args() args: MutationAssignPaymentMethodsToChannelArgs,
+    ): Promise<Array<Translated<PaymentMethod>>> {
+        return await this.paymentMethodService.assignPaymentMethodsToChannel(ctx, args.input);
+    }
+
+    @Transaction()
+    @Mutation()
+    @Allow(Permission.DeleteSettings, Permission.DeletePaymentMethod)
+    async removePaymentMethodsFromChannel(
+        @Ctx() ctx: RequestContext,
+        @Args() args: MutationRemovePaymentMethodsFromChannelArgs,
+    ): Promise<Array<Translated<PaymentMethod>>> {
+        return await this.paymentMethodService.removePaymentMethodsFromChannel(ctx, args.input);
+    }
 }

+ 23 - 0
packages/core/src/api/resolvers/admin/shipping-method.resolver.ts

@@ -2,9 +2,11 @@ import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
 import {
     ConfigurableOperationDefinition,
     DeletionResponse,
+    MutationAssignShippingMethodsToChannelArgs,
     MutationCreateShippingMethodArgs,
     MutationDeleteShippingMethodArgs,
     MutationDeleteShippingMethodsArgs,
+    MutationRemoveShippingMethodsFromChannelArgs,
     MutationUpdateShippingMethodArgs,
     Permission,
     QueryShippingMethodArgs,
@@ -14,6 +16,7 @@ import {
 } from '@vendure/common/lib/generated-types';
 import { PaginatedList } from '@vendure/common/lib/shared-types';
 
+import { Translated } from '../../../common/index';
 import { ShippingMethod } from '../../../entity/shipping-method/shipping-method.entity';
 import { OrderTestingService } from '../../../service/services/order-testing.service';
 import { ShippingMethodService } from '../../../service/services/shipping-method.service';
@@ -127,4 +130,24 @@ export class ShippingMethodResolver {
         const { input } = args;
         return this.orderTestingService.testEligibleShippingMethods(ctx, input);
     }
+
+    @Transaction()
+    @Mutation()
+    @Allow(Permission.UpdateSettings, Permission.UpdateShippingMethod)
+    async assignShippingMethodsToChannel(
+        @Ctx() ctx: RequestContext,
+        @Args() args: MutationAssignShippingMethodsToChannelArgs,
+    ): Promise<Array<Translated<ShippingMethod>>> {
+        return await this.shippingMethodService.assignShippingMethodsToChannel(ctx, args.input);
+    }
+
+    @Transaction()
+    @Mutation()
+    @Allow(Permission.DeleteSettings, Permission.DeleteShippingMethod)
+    async removeShippingMethodsFromChannel(
+        @Ctx() ctx: RequestContext,
+        @Args() args: MutationRemoveShippingMethodsFromChannelArgs,
+    ): Promise<Array<Translated<ShippingMethod>>> {
+        return await this.shippingMethodService.removeShippingMethodsFromChannel(ctx, args.input);
+    }
 }

+ 16 - 0
packages/core/src/api/schema/admin-api/payment-method.api.graphql

@@ -14,6 +14,12 @@ type Mutation {
     deletePaymentMethod(id: ID!, force: Boolean): DeletionResponse!
     "Delete multiple PaymentMethods"
     deletePaymentMethods(ids: [ID!]!, force: Boolean): [DeletionResponse!]!
+
+    "Assigns PaymentMethods to the specified Channel"
+    assignPaymentMethodsToChannel(input: AssignPaymentMethodsToChannelInput!): [PaymentMethod!]!
+
+    "Removes PaymentMethods from the specified Channel"
+    removePaymentMethodsFromChannel(input: RemovePaymentMethodsFromChannelInput!): [PaymentMethod!]!
 }
 
 type PaymentMethodList implements PaginatedList {
@@ -47,3 +53,13 @@ input UpdatePaymentMethodInput {
     handler: ConfigurableOperationInput
     translations: [PaymentMethodTranslationInput!]
 }
+
+input AssignPaymentMethodsToChannelInput {
+    paymentMethodIds: [ID!]!
+    channelId: ID!
+}
+
+input RemovePaymentMethodsFromChannelInput {
+    paymentMethodIds: [ID!]!
+    channelId: ID!
+}

+ 16 - 0
packages/core/src/api/schema/admin-api/shipping-method.api.graphql

@@ -17,6 +17,12 @@ type Mutation {
     deleteShippingMethod(id: ID!): DeletionResponse!
     "Delete multiple ShippingMethods"
     deleteShippingMethods(ids: [ID!]!): [DeletionResponse!]!
+
+    "Assigns ShippingMethods to the specified Channel"
+    assignShippingMethodsToChannel(input: AssignShippingMethodsToChannelInput!): [ShippingMethod!]!
+
+    "Removes ShippingMethods from the specified Channel"
+    removeShippingMethodsFromChannel(input: RemoveShippingMethodsFromChannelInput!): [ShippingMethod!]!
 }
 
 # generated by generateListOptions function
@@ -73,3 +79,13 @@ type TestShippingMethodQuote {
     priceWithTax: Money!
     metadata: JSON
 }
+
+input AssignShippingMethodsToChannelInput {
+    shippingMethodIds: [ID!]!
+    channelId: ID!
+}
+
+input RemoveShippingMethodsFromChannelInput {
+    shippingMethodIds: [ID!]!
+    channelId: ID!
+}

+ 1 - 1
packages/core/src/service/services/collection.service.ts

@@ -839,7 +839,7 @@ export class CollectionService implements OnModuleInit {
         }
         const defaultChannel = await this.channelService.getDefaultChannel(ctx);
         if (idsAreEqual(input.channelId, defaultChannel.id)) {
-            throw new UserInputError('error.collections-cannot-be-removed-from-default-channel');
+            throw new UserInputError('error.items-cannot-be-removed-from-default-channel');
         }
         const collectionsToRemove = await this.connection
             .getRepository(ctx, Collection)

+ 1 - 1
packages/core/src/service/services/facet.service.ts

@@ -322,7 +322,7 @@ export class FacetService {
         }
         const defaultChannel = await this.channelService.getDefaultChannel(ctx);
         if (idsAreEqual(input.channelId, defaultChannel.id)) {
-            throw new UserInputError('error.facets-cannot-be-removed-from-default-channel');
+            throw new UserInputError('error.items-cannot-be-removed-from-default-channel');
         }
         const facetsToRemove = await this.connection
             .getRepository(ctx, Facet)

+ 60 - 1
packages/core/src/service/services/payment-method.service.ts

@@ -1,10 +1,13 @@
 import { Injectable } from '@nestjs/common';
 import { PaymentMethodQuote } from '@vendure/common/lib/generated-shop-types';
 import {
+    AssignPaymentMethodsToChannelInput,
     ConfigurableOperationDefinition,
     CreatePaymentMethodInput,
     DeletionResponse,
     DeletionResult,
+    Permission,
+    RemovePaymentMethodsFromChannelInput,
     UpdatePaymentMethodInput,
 } from '@vendure/common/lib/generated-types';
 import { omit } from '@vendure/common/lib/omit';
@@ -13,7 +16,8 @@ import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
 
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/index';
-import { UserInputError } from '../../common/error/errors';
+import { ForbiddenError, UserInputError } from '../../common/error/errors';
+import { Translated } from '../../common/index';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
 import { ConfigService } from '../../config/config.service';
@@ -33,6 +37,7 @@ import { TranslatorService } from '../helpers/translator/translator.service';
 import { patchEntity } from '../helpers/utils/patch-entity';
 
 import { ChannelService } from './channel.service';
+import { RoleService } from './role.service';
 
 /**
  * @description
@@ -45,6 +50,7 @@ export class PaymentMethodService {
     constructor(
         private connection: TransactionalConnection,
         private configService: ConfigService,
+        private roleService: RoleService,
         private listQueryBuilder: ListQueryBuilder,
         private eventBus: EventBus,
         private configArgService: ConfigArgService,
@@ -188,6 +194,59 @@ export class PaymentMethodService {
         }
     }
 
+    async assignPaymentMethodsToChannel(
+        ctx: RequestContext,
+        input: AssignPaymentMethodsToChannelInput,
+    ): Promise<Array<Translated<PaymentMethod>>> {
+        const hasPermission = await this.roleService.userHasAnyPermissionsOnChannel(ctx, input.channelId, [
+            Permission.UpdatePaymentMethod,
+            Permission.UpdateSettings,
+        ]);
+        if (!hasPermission) {
+            throw new ForbiddenError();
+        }
+        for (const paymentMethodId of input.paymentMethodIds) {
+            const paymentMethod = await this.connection.findOneInChannel(
+                ctx,
+                PaymentMethod,
+                paymentMethodId,
+                ctx.channelId,
+            );
+            await this.channelService.assignToChannels(ctx, PaymentMethod, paymentMethodId, [
+                input.channelId,
+            ]);
+        }
+        return this.connection
+            .findByIdsInChannel(ctx, PaymentMethod, input.paymentMethodIds, ctx.channelId, {})
+            .then(methods => methods.map(method => this.translator.translate(method, ctx)));
+    }
+
+    async removePaymentMethodsFromChannel(
+        ctx: RequestContext,
+        input: RemovePaymentMethodsFromChannelInput,
+    ): Promise<Array<Translated<PaymentMethod>>> {
+        const hasPermission = await this.roleService.userHasAnyPermissionsOnChannel(ctx, input.channelId, [
+            Permission.DeletePaymentMethod,
+            Permission.DeleteSettings,
+        ]);
+        if (!hasPermission) {
+            throw new ForbiddenError();
+        }
+        const defaultChannel = await this.channelService.getDefaultChannel(ctx);
+        if (idsAreEqual(input.channelId, defaultChannel.id)) {
+            throw new UserInputError('error.items-cannot-be-removed-from-default-channel');
+        }
+        for (const paymentMethodId of input.paymentMethodIds) {
+            const paymentMethod = await this.connection.getEntityOrThrow(ctx, PaymentMethod, paymentMethodId);
+            await this.channelService.removeFromChannels(ctx, PaymentMethod, paymentMethodId, [
+                input.channelId,
+            ]);
+        }
+        return this.connection
+            .findByIdsInChannel(ctx, PaymentMethod, input.paymentMethodIds, ctx.channelId, {})
+            .then(methods => methods.map(method => this.translator.translate(method, ctx)));
+    }
+
     getPaymentMethodEligibilityCheckers(ctx: RequestContext): ConfigurableOperationDefinition[] {
         return this.configArgService
             .getDefinitions('PaymentMethodEligibilityChecker')

+ 1 - 1
packages/core/src/service/services/product-variant.service.ts

@@ -706,7 +706,7 @@ export class ProductVariantService {
         }
         const defaultChannel = await this.channelService.getDefaultChannel(ctx);
         if (idsAreEqual(input.channelId, defaultChannel.id)) {
-            throw new UserInputError('error.products-cannot-be-removed-from-default-channel');
+            throw new UserInputError('error.items-cannot-be-removed-from-default-channel');
         }
         const variants = await this.connection
             .getRepository(ctx, ProductVariant)

+ 0 - 8
packages/core/src/service/services/promotion.service.ts

@@ -208,10 +208,6 @@ export class PromotionService {
         ctx: RequestContext,
         input: AssignPromotionsToChannelInput,
     ): Promise<Promotion[]> {
-        const defaultChannel = await this.channelService.getDefaultChannel(ctx);
-        if (!idsAreEqual(ctx.channelId, defaultChannel.id)) {
-            throw new IllegalOperationError('promotion-channels-can-only-be-changed-from-default-channel');
-        }
         const promotions = await this.connection.findByIdsInChannel(
             ctx,
             Promotion,
@@ -226,10 +222,6 @@ export class PromotionService {
     }
 
     async removePromotionsFromChannel(ctx: RequestContext, input: RemovePromotionsFromChannelInput) {
-        const defaultChannel = await this.channelService.getDefaultChannel(ctx);
-        if (!idsAreEqual(ctx.channelId, defaultChannel.id)) {
-            throw new IllegalOperationError('promotion-channels-can-only-be-changed-from-default-channel');
-        }
         const promotions = await this.connection.findByIdsInChannel(
             ctx,
             Promotion,

+ 69 - 6
packages/core/src/service/services/shipping-method.service.ts

@@ -1,9 +1,12 @@
 import { Injectable } from '@nestjs/common';
 import {
+    AssignShippingMethodsToChannelInput,
     ConfigurableOperationDefinition,
     CreateShippingMethodInput,
     DeletionResponse,
     DeletionResult,
+    Permission,
+    RemoveShippingMethodsFromChannelInput,
     UpdateShippingMethodInput,
 } from '@vendure/common/lib/generated-types';
 import { omit } from '@vendure/common/lib/omit';
@@ -12,13 +15,14 @@ import { IsNull } from 'typeorm';
 
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/index';
-import { EntityNotFoundError } from '../../common/error/errors';
+import { EntityNotFoundError, ForbiddenError, UserInputError } from '../../common/error/errors';
+import { Translated } from '../../common/index';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
 import { ConfigService } from '../../config/config.service';
 import { Logger } from '../../config/logger/vendure-logger';
 import { TransactionalConnection } from '../../connection/transactional-connection';
-import { Channel } from '../../entity/channel/channel.entity';
+import { ShippingMethod } from '../../entity/index';
 import { ShippingMethodTranslation } from '../../entity/shipping-method/shipping-method-translation.entity';
 import { ShippingMethod } from '../../entity/shipping-method/shipping-method.entity';
 import { EventBus } from '../../event-bus';
@@ -30,6 +34,7 @@ import { TranslatableSaver } from '../helpers/translatable-saver/translatable-sa
 import { TranslatorService } from '../helpers/translator/translator.service';
 
 import { ChannelService } from './channel.service';
+import { RoleService } from './role.service';
 
 /**
  * @description
@@ -42,6 +47,7 @@ export class ShippingMethodService {
     constructor(
         private connection: TransactionalConnection,
         private configService: ConfigService,
+        private roleService: RoleService,
         private listQueryBuilder: ListQueryBuilder,
         private channelService: ChannelService,
         private configArgService: ConfigArgService,
@@ -66,7 +72,7 @@ export class ShippingMethodService {
         ctx: RequestContext,
         options?: ListQueryOptions<ShippingMethod>,
         relations: RelationPaths<ShippingMethod> = [],
-    ): Promise<PaginatedList<ShippingMethod>> {
+    ): Promise<PaginatedList<Translated<ShippingMethod>>> {
         return this.listQueryBuilder
             .build(ShippingMethod, options, {
                 relations,
@@ -86,7 +92,7 @@ export class ShippingMethodService {
         shippingMethodId: ID,
         includeDeleted = false,
         relations: RelationPaths<ShippingMethod> = [],
-    ): Promise<ShippingMethod | undefined> {
+    ): Promise<Translated<ShippingMethod> | undefined> {
         const shippingMethod = await this.connection.findOneInChannel(
             ctx,
             ShippingMethod,
@@ -100,7 +106,7 @@ export class ShippingMethodService {
         return (shippingMethod && this.translator.translate(shippingMethod, ctx)) ?? undefined;
     }
 
-    async create(ctx: RequestContext, input: CreateShippingMethodInput): Promise<ShippingMethod> {
+    async create(ctx: RequestContext, input: CreateShippingMethodInput): Promise<Translated<ShippingMethod>> {
         const shippingMethod = await this.translatableSaver.create({
             ctx,
             input,
@@ -132,7 +138,7 @@ export class ShippingMethodService {
         return assertFound(this.findOne(ctx, newShippingMethod.id));
     }
 
-    async update(ctx: RequestContext, input: UpdateShippingMethodInput): Promise<ShippingMethod> {
+    async update(ctx: RequestContext, input: UpdateShippingMethodInput): Promise<Translated<ShippingMethod>> {
         const shippingMethod = await this.findOne(ctx, input.id);
         if (!shippingMethod) {
             throw new EntityNotFoundError('ShippingMethod', input.id);
@@ -187,6 +193,63 @@ export class ShippingMethodService {
         };
     }
 
+    async assignShippingMethodsToChannel(
+        ctx: RequestContext,
+        input: AssignShippingMethodsToChannelInput,
+    ): Promise<Array<Translated<ShippingMethod>>> {
+        const hasPermission = await this.roleService.userHasAnyPermissionsOnChannel(ctx, input.channelId, [
+            Permission.UpdateShippingMethod,
+            Permission.UpdateSettings,
+        ]);
+        if (!hasPermission) {
+            throw new ForbiddenError();
+        }
+        for (const shippingMethodId of input.shippingMethodIds) {
+            const shippingMethod = await this.connection.findOneInChannel(
+                ctx,
+                ShippingMethod,
+                shippingMethodId,
+                ctx.channelId,
+            );
+            await this.channelService.assignToChannels(ctx, ShippingMethod, shippingMethodId, [
+                input.channelId,
+            ]);
+        }
+        return this.connection
+            .findByIdsInChannel(ctx, ShippingMethod, input.shippingMethodIds, ctx.channelId, {})
+            .then(methods => methods.map(method => this.translator.translate(method, ctx)));
+    }
+
+    async removeShippingMethodsFromChannel(
+        ctx: RequestContext,
+        input: RemoveShippingMethodsFromChannelInput,
+    ): Promise<Array<Translated<ShippingMethod>>> {
+        const hasPermission = await this.roleService.userHasAnyPermissionsOnChannel(ctx, input.channelId, [
+            Permission.DeleteShippingMethod,
+            Permission.DeleteSettings,
+        ]);
+        if (!hasPermission) {
+            throw new ForbiddenError();
+        }
+        const defaultChannel = await this.channelService.getDefaultChannel(ctx);
+        if (idsAreEqual(input.channelId, defaultChannel.id)) {
+            throw new UserInputError('error.items-cannot-be-removed-from-default-channel');
+        }
+        for (const shippingMethodId of input.shippingMethodIds) {
+            const shippingMethod = await this.connection.getEntityOrThrow(
+                ctx,
+                ShippingMethod,
+                shippingMethodId,
+            );
+            await this.channelService.removeFromChannels(ctx, ShippingMethod, shippingMethodId, [
+                input.channelId,
+            ]);
+        }
+        return this.connection
+            .findByIdsInChannel(ctx, ShippingMethod, input.shippingMethodIds, ctx.channelId, {})
+            .then(methods => methods.map(method => this.translator.translate(method, ctx)));
+    }
+
     getShippingEligibilityCheckers(ctx: RequestContext): ConfigurableOperationDefinition[] {
         return this.configArgService
             .getDefinitions('ShippingEligibilityChecker')

+ 1 - 1
packages/core/src/service/services/stock-location.service.ts

@@ -175,7 +175,7 @@ export class StockLocationService {
         }
         const defaultChannel = await this.channelService.getDefaultChannel(ctx);
         if (idsAreEqual(input.channelId, defaultChannel.id)) {
-            throw new UserInputError('error.stock-locations-cannot-be-removed-from-default-channel');
+            throw new UserInputError('error.items-cannot-be-removed-from-default-channel');
         }
         for (const stockLocationId of input.stockLocationIds) {
             const stockLocation = await this.connection.getEntityOrThrow(ctx, StockLocation, stockLocationId);

+ 48 - 0
packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts

@@ -242,6 +242,11 @@ export type AssignFacetsToChannelInput = {
   facetIds: Array<Scalars['ID']>;
 };
 
+export type AssignPaymentMethodsToChannelInput = {
+  channelId: Scalars['ID'];
+  paymentMethodIds: Array<Scalars['ID']>;
+};
+
 export type AssignProductVariantsToChannelInput = {
   channelId: Scalars['ID'];
   priceFactor?: InputMaybe<Scalars['Float']>;
@@ -259,6 +264,11 @@ export type AssignPromotionsToChannelInput = {
   promotionIds: Array<Scalars['ID']>;
 };
 
+export type AssignShippingMethodsToChannelInput = {
+  channelId: Scalars['ID'];
+  shippingMethodIds: Array<Scalars['ID']>;
+};
+
 export type AssignStockLocationsToChannelInput = {
   channelId: Scalars['ID'];
   stockLocationIds: Array<Scalars['ID']>;
@@ -2484,6 +2494,8 @@ export type Mutation = {
   assignCollectionsToChannel: Array<Collection>;
   /** Assigns Facets to the specified Channel */
   assignFacetsToChannel: Array<Facet>;
+  /** Assigns PaymentMethods to the specified Channel */
+  assignPaymentMethodsToChannel: Array<PaymentMethod>;
   /** Assigns ProductVariants to the specified Channel */
   assignProductVariantsToChannel: Array<ProductVariant>;
   /** Assigns all ProductVariants of Product to the specified Channel */
@@ -2492,6 +2504,8 @@ export type Mutation = {
   assignPromotionsToChannel: Array<Promotion>;
   /** Assign a Role to an Administrator */
   assignRoleToAdministrator: Administrator;
+  /** Assigns ShippingMethods to the specified Channel */
+  assignShippingMethodsToChannel: Array<ShippingMethod>;
   /** Assigns StockLocations to the specified Channel */
   assignStockLocationsToChannel: Array<StockLocation>;
   /** Authenticates the user using a named authentication strategy */
@@ -2668,6 +2682,8 @@ export type Mutation = {
    * as well as removing any of the group's options from the Product's ProductVariants.
    */
   removeOptionGroupFromProduct: RemoveOptionGroupFromProductResult;
+  /** Removes PaymentMethods from the specified Channel */
+  removePaymentMethodsFromChannel: Array<PaymentMethod>;
   /** Removes ProductVariants from the specified Channel */
   removeProductVariantsFromChannel: Array<ProductVariant>;
   /** Removes all ProductVariants of Product from the specified Channel */
@@ -2676,6 +2692,8 @@ export type Mutation = {
   removePromotionsFromChannel: Array<Promotion>;
   /** Remove all settled jobs in the given queues older than the given date. Returns the number of jobs deleted. */
   removeSettledJobs: Scalars['Int'];
+  /** Removes ShippingMethods from the specified Channel */
+  removeShippingMethodsFromChannel: Array<ShippingMethod>;
   /** Removes StockLocations from the specified Channel */
   removeStockLocationsFromChannel: Array<StockLocation>;
   runPendingSearchIndexUpdates: Success;
@@ -2823,6 +2841,11 @@ export type MutationAssignFacetsToChannelArgs = {
 };
 
 
+export type MutationAssignPaymentMethodsToChannelArgs = {
+  input: AssignPaymentMethodsToChannelInput;
+};
+
+
 export type MutationAssignProductVariantsToChannelArgs = {
   input: AssignProductVariantsToChannelInput;
 };
@@ -2844,6 +2867,11 @@ export type MutationAssignRoleToAdministratorArgs = {
 };
 
 
+export type MutationAssignShippingMethodsToChannelArgs = {
+  input: AssignShippingMethodsToChannelInput;
+};
+
+
 export type MutationAssignStockLocationsToChannelArgs = {
   input: AssignStockLocationsToChannelInput;
 };
@@ -3305,6 +3333,11 @@ export type MutationRemoveOptionGroupFromProductArgs = {
 };
 
 
+export type MutationRemovePaymentMethodsFromChannelArgs = {
+  input: RemovePaymentMethodsFromChannelInput;
+};
+
+
 export type MutationRemoveProductVariantsFromChannelArgs = {
   input: RemoveProductVariantsFromChannelInput;
 };
@@ -3326,6 +3359,11 @@ export type MutationRemoveSettledJobsArgs = {
 };
 
 
+export type MutationRemoveShippingMethodsFromChannelArgs = {
+  input: RemoveShippingMethodsFromChannelInput;
+};
+
+
 export type MutationRemoveStockLocationsFromChannelArgs = {
   input: RemoveStockLocationsFromChannelInput;
 };
@@ -5185,6 +5223,11 @@ export type RemoveOptionGroupFromProductResult = Product | ProductOptionInUseErr
 
 export type RemoveOrderItemsResult = Order | OrderModificationError;
 
+export type RemovePaymentMethodsFromChannelInput = {
+  channelId: Scalars['ID'];
+  paymentMethodIds: Array<Scalars['ID']>;
+};
+
 export type RemoveProductVariantsFromChannelInput = {
   channelId: Scalars['ID'];
   productVariantIds: Array<Scalars['ID']>;
@@ -5200,6 +5243,11 @@ export type RemovePromotionsFromChannelInput = {
   promotionIds: Array<Scalars['ID']>;
 };
 
+export type RemoveShippingMethodsFromChannelInput = {
+  channelId: Scalars['ID'];
+  shippingMethodIds: Array<Scalars['ID']>;
+};
+
 export type RemoveStockLocationsFromChannelInput = {
   channelId: Scalars['ID'];
   stockLocationIds: Array<Scalars['ID']>;

+ 48 - 0
packages/payments-plugin/e2e/graphql/generated-admin-types.ts

@@ -242,6 +242,11 @@ export type AssignFacetsToChannelInput = {
   facetIds: Array<Scalars['ID']>;
 };
 
+export type AssignPaymentMethodsToChannelInput = {
+  channelId: Scalars['ID'];
+  paymentMethodIds: Array<Scalars['ID']>;
+};
+
 export type AssignProductVariantsToChannelInput = {
   channelId: Scalars['ID'];
   priceFactor?: InputMaybe<Scalars['Float']>;
@@ -259,6 +264,11 @@ export type AssignPromotionsToChannelInput = {
   promotionIds: Array<Scalars['ID']>;
 };
 
+export type AssignShippingMethodsToChannelInput = {
+  channelId: Scalars['ID'];
+  shippingMethodIds: Array<Scalars['ID']>;
+};
+
 export type AssignStockLocationsToChannelInput = {
   channelId: Scalars['ID'];
   stockLocationIds: Array<Scalars['ID']>;
@@ -2484,6 +2494,8 @@ export type Mutation = {
   assignCollectionsToChannel: Array<Collection>;
   /** Assigns Facets to the specified Channel */
   assignFacetsToChannel: Array<Facet>;
+  /** Assigns PaymentMethods to the specified Channel */
+  assignPaymentMethodsToChannel: Array<PaymentMethod>;
   /** Assigns ProductVariants to the specified Channel */
   assignProductVariantsToChannel: Array<ProductVariant>;
   /** Assigns all ProductVariants of Product to the specified Channel */
@@ -2492,6 +2504,8 @@ export type Mutation = {
   assignPromotionsToChannel: Array<Promotion>;
   /** Assign a Role to an Administrator */
   assignRoleToAdministrator: Administrator;
+  /** Assigns ShippingMethods to the specified Channel */
+  assignShippingMethodsToChannel: Array<ShippingMethod>;
   /** Assigns StockLocations to the specified Channel */
   assignStockLocationsToChannel: Array<StockLocation>;
   /** Authenticates the user using a named authentication strategy */
@@ -2668,6 +2682,8 @@ export type Mutation = {
    * as well as removing any of the group's options from the Product's ProductVariants.
    */
   removeOptionGroupFromProduct: RemoveOptionGroupFromProductResult;
+  /** Removes PaymentMethods from the specified Channel */
+  removePaymentMethodsFromChannel: Array<PaymentMethod>;
   /** Removes ProductVariants from the specified Channel */
   removeProductVariantsFromChannel: Array<ProductVariant>;
   /** Removes all ProductVariants of Product from the specified Channel */
@@ -2676,6 +2692,8 @@ export type Mutation = {
   removePromotionsFromChannel: Array<Promotion>;
   /** Remove all settled jobs in the given queues older than the given date. Returns the number of jobs deleted. */
   removeSettledJobs: Scalars['Int'];
+  /** Removes ShippingMethods from the specified Channel */
+  removeShippingMethodsFromChannel: Array<ShippingMethod>;
   /** Removes StockLocations from the specified Channel */
   removeStockLocationsFromChannel: Array<StockLocation>;
   runPendingSearchIndexUpdates: Success;
@@ -2823,6 +2841,11 @@ export type MutationAssignFacetsToChannelArgs = {
 };
 
 
+export type MutationAssignPaymentMethodsToChannelArgs = {
+  input: AssignPaymentMethodsToChannelInput;
+};
+
+
 export type MutationAssignProductVariantsToChannelArgs = {
   input: AssignProductVariantsToChannelInput;
 };
@@ -2844,6 +2867,11 @@ export type MutationAssignRoleToAdministratorArgs = {
 };
 
 
+export type MutationAssignShippingMethodsToChannelArgs = {
+  input: AssignShippingMethodsToChannelInput;
+};
+
+
 export type MutationAssignStockLocationsToChannelArgs = {
   input: AssignStockLocationsToChannelInput;
 };
@@ -3305,6 +3333,11 @@ export type MutationRemoveOptionGroupFromProductArgs = {
 };
 
 
+export type MutationRemovePaymentMethodsFromChannelArgs = {
+  input: RemovePaymentMethodsFromChannelInput;
+};
+
+
 export type MutationRemoveProductVariantsFromChannelArgs = {
   input: RemoveProductVariantsFromChannelInput;
 };
@@ -3326,6 +3359,11 @@ export type MutationRemoveSettledJobsArgs = {
 };
 
 
+export type MutationRemoveShippingMethodsFromChannelArgs = {
+  input: RemoveShippingMethodsFromChannelInput;
+};
+
+
 export type MutationRemoveStockLocationsFromChannelArgs = {
   input: RemoveStockLocationsFromChannelInput;
 };
@@ -5185,6 +5223,11 @@ export type RemoveOptionGroupFromProductResult = Product | ProductOptionInUseErr
 
 export type RemoveOrderItemsResult = Order | OrderModificationError;
 
+export type RemovePaymentMethodsFromChannelInput = {
+  channelId: Scalars['ID'];
+  paymentMethodIds: Array<Scalars['ID']>;
+};
+
 export type RemoveProductVariantsFromChannelInput = {
   channelId: Scalars['ID'];
   productVariantIds: Array<Scalars['ID']>;
@@ -5200,6 +5243,11 @@ export type RemovePromotionsFromChannelInput = {
   promotionIds: Array<Scalars['ID']>;
 };
 
+export type RemoveShippingMethodsFromChannelInput = {
+  channelId: Scalars['ID'];
+  shippingMethodIds: Array<Scalars['ID']>;
+};
+
 export type RemoveStockLocationsFromChannelInput = {
   channelId: Scalars['ID'];
   stockLocationIds: Array<Scalars['ID']>;

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
schema-admin.json


Некоторые файлы не были показаны из-за большого количества измененных файлов