mv.service.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import { Injectable } from '@nestjs/common';
  2. import { CreateAdministratorInput, Permission } from '@vendure/common/lib/generated-types';
  3. import { normalizeString } from '@vendure/common/lib/normalize-string';
  4. import {
  5. AdministratorService,
  6. Channel,
  7. ChannelService,
  8. ConfigService,
  9. defaultShippingCalculator,
  10. InternalServerError,
  11. isGraphQlErrorResult,
  12. manualFulfillmentHandler,
  13. RequestContext,
  14. RoleService,
  15. SellerService,
  16. ShippingMethod,
  17. ShippingMethodService,
  18. StockLocation,
  19. StockLocationService,
  20. TaxSetting,
  21. } from '@vendure/core';
  22. import { multivendorShippingEligibilityChecker } from '../config/mv-shipping-eligibility-checker';
  23. import { CreateSellerInput } from '../types';
  24. @Injectable()
  25. export class MultivendorService {
  26. constructor(
  27. private administratorService: AdministratorService,
  28. private sellerService: SellerService,
  29. private roleService: RoleService,
  30. private channelService: ChannelService,
  31. private shippingMethodService: ShippingMethodService,
  32. private configService: ConfigService,
  33. private stockLocationService: StockLocationService,
  34. ) {}
  35. async registerNewSeller(ctx: RequestContext, input: { shopName: string; seller: CreateSellerInput }) {
  36. const channel = await this.createSellerChannelRoleAdmin(ctx, input);
  37. await this.createSellerShippingMethod(ctx, input.shopName, channel);
  38. await this.createSellerStockLocation(ctx, input.shopName, channel);
  39. return channel;
  40. }
  41. private async createSellerShippingMethod(ctx: RequestContext, shopName: string, sellerChannel: Channel) {
  42. const defaultChannel = await this.channelService.getDefaultChannel(ctx);
  43. const { shippingEligibilityCheckers, shippingCalculators, fulfillmentHandlers } =
  44. this.configService.shippingOptions;
  45. const shopCode = normalizeString(shopName, '-');
  46. const checker = shippingEligibilityCheckers.find(
  47. c => c.code === multivendorShippingEligibilityChecker.code,
  48. );
  49. const calculator = shippingCalculators.find(c => c.code === defaultShippingCalculator.code);
  50. const fulfillmentHandler = fulfillmentHandlers.find(h => h.code === manualFulfillmentHandler.code);
  51. if (!checker) {
  52. throw new InternalServerError(
  53. 'Could not find a suitable ShippingEligibilityChecker for the seller',
  54. );
  55. }
  56. if (!calculator) {
  57. throw new InternalServerError('Could not find a suitable ShippingCalculator for the seller');
  58. }
  59. if (!fulfillmentHandler) {
  60. throw new InternalServerError('Could not find a suitable FulfillmentHandler for the seller');
  61. }
  62. const shippingMethod = await this.shippingMethodService.create(ctx, {
  63. code: `${shopCode}-shipping`,
  64. checker: {
  65. code: checker.code,
  66. arguments: [],
  67. },
  68. calculator: {
  69. code: calculator.code,
  70. arguments: [
  71. { name: 'rate', value: '500' },
  72. { name: 'includesTax', value: TaxSetting.auto },
  73. { name: 'taxRate', value: '20' },
  74. ],
  75. },
  76. fulfillmentHandler: fulfillmentHandler.code,
  77. translations: [
  78. {
  79. languageCode: defaultChannel.defaultLanguageCode,
  80. name: `Standard Shipping for ${shopName}`,
  81. },
  82. ],
  83. });
  84. await this.channelService.assignToChannels(ctx, ShippingMethod, shippingMethod.id, [
  85. sellerChannel.id,
  86. ]);
  87. }
  88. private async createSellerStockLocation(ctx: RequestContext, shopName: string, sellerChannel: Channel) {
  89. const stockLocation = await this.stockLocationService.create(ctx, {
  90. name: `${shopName} Warehouse`,
  91. });
  92. await this.channelService.assignToChannels(ctx, StockLocation, stockLocation.id, [sellerChannel.id]);
  93. }
  94. private async createSellerChannelRoleAdmin(
  95. ctx: RequestContext,
  96. input: { shopName: string; seller: CreateSellerInput },
  97. ) {
  98. const defaultChannel = await this.channelService.getDefaultChannel(ctx);
  99. const shopCode = normalizeString(input.shopName, '-');
  100. const seller = await this.sellerService.create(ctx, {
  101. name: input.shopName,
  102. customFields: {
  103. connectedAccountId: Math.random().toString(30).substring(3),
  104. },
  105. });
  106. const channel = await this.channelService.create(ctx, {
  107. code: shopCode,
  108. sellerId: seller.id,
  109. token: `${shopCode}-token`,
  110. currencyCode: defaultChannel.defaultCurrencyCode,
  111. defaultLanguageCode: defaultChannel.defaultLanguageCode,
  112. pricesIncludeTax: defaultChannel.pricesIncludeTax,
  113. defaultShippingZoneId: defaultChannel.defaultShippingZone.id,
  114. defaultTaxZoneId: defaultChannel.defaultTaxZone.id,
  115. });
  116. if (isGraphQlErrorResult(channel)) {
  117. throw new InternalServerError(channel.message);
  118. }
  119. const superAdminRole = await this.roleService.getSuperAdminRole(ctx);
  120. const customerRole = await this.roleService.getCustomerRole(ctx);
  121. await this.roleService.assignRoleToChannel(ctx, superAdminRole.id, channel.id);
  122. const role = await this.roleService.create(ctx, {
  123. code: `${shopCode}-admin`,
  124. channelIds: [channel.id],
  125. description: `Administrator of ${input.shopName}`,
  126. permissions: [
  127. Permission.CreateCatalog,
  128. Permission.UpdateCatalog,
  129. Permission.ReadCatalog,
  130. Permission.DeleteCatalog,
  131. Permission.CreateOrder,
  132. Permission.ReadOrder,
  133. Permission.UpdateOrder,
  134. Permission.DeleteOrder,
  135. Permission.ReadCustomer,
  136. Permission.ReadPaymentMethod,
  137. Permission.ReadShippingMethod,
  138. Permission.ReadPromotion,
  139. Permission.ReadCountry,
  140. Permission.ReadZone,
  141. Permission.CreateCustomer,
  142. Permission.UpdateCustomer,
  143. Permission.DeleteCustomer,
  144. Permission.CreateTag,
  145. Permission.ReadTag,
  146. Permission.UpdateTag,
  147. Permission.DeleteTag,
  148. ],
  149. });
  150. const administrator = await this.administratorService.create(ctx, {
  151. firstName: input.seller.firstName,
  152. lastName: input.seller.lastName,
  153. emailAddress: input.seller.emailAddress,
  154. password: input.seller.password,
  155. roleIds: [role.id],
  156. });
  157. return channel;
  158. }
  159. }