token-active-order-plugin.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import { Args, Mutation, Parent, ResolveField, Resolver } from '@nestjs/graphql';
  2. import { ID } from '@vendure/common/lib/shared-types';
  3. import {
  4. ActiveOrderStrategy,
  5. Ctx,
  6. CustomerService,
  7. idsAreEqual,
  8. Injector,
  9. Order,
  10. OrderService,
  11. PluginCommonModule,
  12. RequestContext,
  13. Transaction,
  14. TransactionalConnection,
  15. VendurePlugin,
  16. } from '@vendure/core';
  17. import { CustomOrderFields } from '@vendure/core/dist/entity/custom-entity-fields';
  18. import { UserInputError } from 'apollo-server-express';
  19. import gql from 'graphql-tag';
  20. declare module '@vendure/core/dist/entity/custom-entity-fields' {
  21. interface CustomOrderFields {
  22. orderToken: string;
  23. }
  24. }
  25. class TokenActiveOrderStrategy implements ActiveOrderStrategy {
  26. readonly name = 'orderToken';
  27. private connection: TransactionalConnection;
  28. private orderService: OrderService;
  29. init(injector: Injector) {
  30. this.connection = injector.get(TransactionalConnection);
  31. this.orderService = injector.get(OrderService);
  32. }
  33. defineInputType = () => gql`
  34. input OrderTokenActiveOrderInput {
  35. token: String
  36. }
  37. `;
  38. async determineActiveOrder(ctx: RequestContext, input: { token: string }) {
  39. const qb = this.connection
  40. .getRepository(ctx, Order)
  41. .createQueryBuilder('order')
  42. .leftJoinAndSelect('order.customer', 'customer')
  43. .leftJoinAndSelect('customer.user', 'user')
  44. .where('order.customFields.orderToken = :orderToken', { orderToken: input.token });
  45. const order = await qb.getOne();
  46. if (!order) {
  47. return;
  48. }
  49. const orderUserId = order.customer && order.customer.user && order.customer.user.id;
  50. if (order.customer && idsAreEqual(orderUserId, ctx.activeUserId)) {
  51. return order;
  52. }
  53. }
  54. }
  55. @Resolver('Order')
  56. export class OrderTokenResolver {
  57. @ResolveField()
  58. orderToken(@Parent() order: Order) {
  59. return order.customFields.orderToken;
  60. }
  61. }
  62. @Resolver()
  63. export class CreateOrderResolver {
  64. constructor(private orderService: OrderService, private customerService: CustomerService) {}
  65. @Mutation()
  66. @Transaction()
  67. async createOrder(@Ctx() ctx: RequestContext, @Args() args: { customerId: ID }) {
  68. const customer = await this.customerService.findOne(ctx, args.customerId);
  69. if (!customer) {
  70. throw new UserInputError('No customer found');
  71. }
  72. const order = await this.orderService.create(ctx, customer.user?.id);
  73. return this.orderService.updateCustomFields(ctx, order.id, {
  74. orderToken: `token-${args.customerId}`,
  75. });
  76. }
  77. }
  78. @VendurePlugin({
  79. imports: [PluginCommonModule],
  80. configuration: config => {
  81. config.customFields.Order.push({
  82. name: 'orderToken',
  83. type: 'string',
  84. internal: true,
  85. });
  86. config.orderOptions.activeOrderStrategy = new TokenActiveOrderStrategy();
  87. return config;
  88. },
  89. shopApiExtensions: {
  90. schema: gql`
  91. extend type Mutation {
  92. createOrder(customerId: ID!): Order!
  93. }
  94. extend type Order {
  95. orderToken: String!
  96. }
  97. `,
  98. resolvers: [OrderTokenResolver, CreateOrderResolver],
  99. },
  100. })
  101. export class TokenActiveOrderPlugin {}