Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Upgrade to V2 #6

Merged
merged 13 commits into from
May 17, 2023
Merged

Feat: Upgrade to V2 #6

merged 13 commits into from
May 17, 2023

Conversation

martijnvdbrug
Copy link
Contributor

Upgrade to support Vendure V2.

image

BREAKING CHANGE

Previous versions of this plugin only sent emails when stock went from <1 to >1, but the plugin now also sends an email when a customer subscribes to a variant that already has stock and the stock is being updated to anything above 1.

This is because previous versions listened for changes in the DB entity ProductVariant, where we could get the stock level before update and after update, thus enabling use to determine when stock went from <1 to >1.

Vendure V2 introduces the concept of stock locations and a custom StockLocationStrategy.

With this new change, the only way to correctly determine a variant's stock level, is to use stockLevelService.getAvailableStockLevel(), but that doesn't give us the stock level before update. Hence, now the plugin sends an email on stock changes that change the stock to anything >1.

This is IMO an acceptable change, considering this is the only scenario that changed:

  1. A customer subscribes to a variant that has 5 available stock (thus is in stock)
  2. The stock of the variant is updated from 5 to 17, and the customer receives an email
    This is technically correct, because the variant is in stock, the only thing is that it was already in stock.

Please let me know what you think of this solution.

@@ -1,6 +1,6 @@

generates:
./src/generated/graphql-shop-api-types.ts:
./src/ui/generated/graphql-shop-api-types.ts:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Place generated inside ui dir, because Admin UI Angular compilation can't access anything outside the ui directory

@@ -19,25 +19,25 @@
"build": "rimraf dist && tsc && copyfiles -u 1 'src/ui/**/*' dist/src/ && copyfiles -u 1 'generated/*' dist/src/generated",
"generate": "graphql-codegen",
"start": "ts-node test/dev-server.ts",
"test": "jest --preset=\"ts-jest\" --forceExit"
"test": "vitest run"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can run yarn vitest to run Vitest in watch mode when developing locally 🦾

*/
@Injectable()
@EventSubscriber()
export class ProductVariantSubscriber implements EntitySubscriberInterface<ProductVariant> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProductVariantSubscriber has been replaced by eventBus.ofType(StockMovementEvent), because in V2 multiple entities (StockLocations) can be responsible for the final saleableStock

@@ -47,11 +54,54 @@ export class BackInStockService {
private productVariantService: ProductVariantService,
private translatorService: TranslatorService,
private eventBus: EventBus,
) {}
@Inject(PLUGIN_INIT_OPTIONS) private options: BackInStockOptions
Copy link
Contributor Author

@martijnvdbrug martijnvdbrug May 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- BackInStockPlugin.options
+ @Inject(PLUGIN_INIT_OPTIONS) private options: BackInStockOptions

BackInStockPlugin.optionsusually works, but you could end up with weird bootstrap scenarios, where BackInStockPlugin.options is undefined. With @Inject we make NestJS responsible for resolving, which is safer.

// Listen for stock movements and update subscriptions
this.eventBus.ofType(StockMovementEvent).subscribe(async event => {
// Refetch variants, because variants in event does not have all properties fetched from DB
const variants = await this.productVariantService.findByIds(event.ctx, event.stockMovements.map(sm => sm.productVariant.id));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

event.stockMovements[0].productVariant only has a partial variant: {id: 1}, so we refetch the entire variant to be able to resolve saleableStockLevel

where: {
id
},
relations: { productVariant: true, channel: true, customer: true },
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New way of fetching relations in TypeOrm 0.3.0.

relations: ['productVariant'] is deprecated: https://github.com/typeorm/typeorm/releases/tag/0.3.0

// SWC required to support decorators used in test plugins
// See https://github.com/vitest-dev/vitest/issues/708#issuecomment-1118628479
// Vite plugin
swc.vite({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use swc in vitest instead of esbuild because of some Typescript decorator transpilation thing: nestjs/nest#9228

Didn't go into details to find out, but I saw that Vendure/Michael is also using it this way in @vendure/core.

@martijnvdbrug martijnvdbrug marked this pull request as ready for review May 16, 2023 12:08
@prasmalla prasmalla merged commit 28bfe92 into calliT-today:main May 17, 2023
@prasmalla
Copy link
Contributor

LGTM) thank you! v2 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants