Skip to content

Commit

Permalink
fix(core): Copy prices in product duplicator (#2900)
Browse files Browse the repository at this point in the history
  • Loading branch information
mschipperheyn authored Jun 18, 2024
1 parent c0f571d commit 18d200c
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 5 deletions.
157 changes: 154 additions & 3 deletions packages/core/e2e/duplicate-entity.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ import {
RoleFragment,
} from './graphql/generated-e2e-admin-types';
import {
ASSIGN_PRODUCT_TO_CHANNEL,
CREATE_ADMINISTRATOR,
CREATE_CHANNEL,
CREATE_COLLECTION,
CREATE_PROMOTION,
CREATE_ROLE,
Expand Down Expand Up @@ -169,9 +171,8 @@ describe('Duplicating entities', () => {
});

it('get entity duplicators', async () => {
const { entityDuplicators } = await adminClient.query<Codegen.GetEntityDuplicatorsQuery>(
GET_ENTITY_DUPLICATORS,
);
const { entityDuplicators } =
await adminClient.query<Codegen.GetEntityDuplicatorsQuery>(GET_ENTITY_DUPLICATORS);

expect(entityDuplicators.find(d => d.code === 'custom-collection-duplicator')).toEqual({
args: [
Expand Down Expand Up @@ -525,6 +526,156 @@ describe('Duplicating entities', () => {
100,
);
});

it('variant prices are duplicated', async () => {
const { duplicateEntity } = await adminClient.query<
Codegen.DuplicateEntityMutation,
Codegen.DuplicateEntityMutationVariables
>(DUPLICATE_ENTITY, {
input: {
entityName: 'Product',
entityId: 'T_1',
duplicatorInput: {
code: 'product-duplicator',
arguments: [
{
name: 'includeVariants',
value: 'true',
},
],
},
},
});

const { product } = await adminClient.query<
Codegen.GetProductWithVariantsQuery,
Codegen.GetProductWithVariantsQueryVariables
>(GET_PRODUCT_WITH_VARIANTS, {
id: duplicateEntity.newEntityId,
});

duplicateEntityGuard.assertSuccess(duplicateEntity);
const variant = product?.variants.find(v => v.sku.startsWith(originalFirstVariant.sku));
// console.log('pv1', duplicateEntity.newEntityId, product!.variants, variant)
expect(variant).not.toBeUndefined();
expect(originalFirstVariant.price).toBeGreaterThan(0);
expect(variant!.price).toBe(originalFirstVariant.price);
});

it('variant prices are duplicated on a channel specific basis', async () => {
const { createChannel } = await adminClient.query<
Codegen.CreateChannelMutation,
Codegen.CreateChannelMutationVariables
>(CREATE_CHANNEL, {
input: {
code: 'second-channel',
token: 'second-channel',
defaultLanguageCode: LanguageCode.en,
currencyCode: Codegen.CurrencyCode.USD,
pricesIncludeTax: false,
defaultShippingZoneId: 'T_1',
defaultTaxZoneId: 'T_1',
},
});

await adminClient.query<
Codegen.AssignProductsToChannelMutation,
Codegen.AssignProductsToChannelMutationVariables
>(ASSIGN_PRODUCT_TO_CHANNEL, {
input: {
channelId: createChannel.id,
productIds: ['T_1'],
},
});

const { product } = await adminClient.query<
Codegen.GetProductWithVariantsQuery,
Codegen.GetProductWithVariantsQueryVariables
>(GET_PRODUCT_WITH_VARIANTS, {
id: 'T_1',
});
const productVariant = product!.variants[0];

adminClient.setChannelToken('second-channel');

await adminClient.query<
Codegen.UpdateProductVariantsMutation,
Codegen.UpdateProductVariantsMutationVariables
>(UPDATE_PRODUCT_VARIANTS, {
input: {
id: productVariant.id,
price: productVariant.price + 150,
},
});

adminClient.setChannelToken('e2e-default-channel');

const { duplicateEntity } = await adminClient.query<
Codegen.DuplicateEntityMutation,
Codegen.DuplicateEntityMutationVariables
>(DUPLICATE_ENTITY, {
input: {
entityName: 'Product',
entityId: 'T_1',
duplicatorInput: {
code: 'product-duplicator',
arguments: [
{
name: 'includeVariants',
value: 'true',
},
],
},
},
});

const { product: productWithVariantChannelNull } = await adminClient.query<
Codegen.GetProductWithVariantsQuery,
Codegen.GetProductWithVariantsQueryVariables
>(GET_PRODUCT_WITH_VARIANTS, {
id: duplicateEntity.newEntityId,
});

const productVariantChannelNull = productWithVariantChannelNull!.variants.find(v =>
v.sku.startsWith(productVariant.sku),
);

expect(productVariantChannelNull!.price).toEqual(productVariant.price);

adminClient.setChannelToken('second-channel');

const { duplicateEntity: duplicateEntitySecondChannel } = await adminClient.query<
Codegen.DuplicateEntityMutation,
Codegen.DuplicateEntityMutationVariables
>(DUPLICATE_ENTITY, {
input: {
entityName: 'Product',
entityId: 'T_1',
duplicatorInput: {
code: 'product-duplicator',
arguments: [
{
name: 'includeVariants',
value: 'true',
},
],
},
},
});

const { product: productWithVariantChannel2 } = await adminClient.query<
Codegen.GetProductWithVariantsQuery,
Codegen.GetProductWithVariantsQueryVariables
>(GET_PRODUCT_WITH_VARIANTS, {
id: duplicateEntitySecondChannel.newEntityId,
});

const productVariantChannel2 = productWithVariantChannel2!.variants.find(v =>
v.sku.startsWith(productVariant.sku),
);

expect(productVariantChannel2!.price).toEqual(productVariant.price + 150);
});
});

describe('Collection duplicator', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '@vendure/common/lib/generated-types';
import { IsNull } from 'typeorm';

import { idsAreEqual } from '../../../common';
import { InternalServerError } from '../../../common/error/errors';
import { Injector } from '../../../common/injector';
import { TransactionalConnection } from '../../../connection/transactional-connection';
Expand Down Expand Up @@ -102,6 +103,7 @@ export const productDuplicator = new EntityDuplicator({
featuredAsset: true,
stockLevels: true,
facetValues: true,
productVariantPrices: true,
},
});
if (product.optionGroups && product.optionGroups.length) {
Expand Down Expand Up @@ -150,7 +152,6 @@ export const productDuplicator = new EntityDuplicator({
options: true,
},
});

const variantInput: CreateProductVariantInput[] = productVariants.map((variant, i) => {
const options = variant.options.map(existingOption => {
const newOption = newOptionGroups
Expand All @@ -163,9 +164,13 @@ export const productDuplicator = new EntityDuplicator({
}
return newOption;
});
const price =
variant.productVariantPrices.find(p => idsAreEqual(p.channelId, ctx.channelId))?.price ??
variant.productVariantPrices[0]?.price;

return {
productId: duplicatedProduct.id,
price: variant.price,
price: price ?? variant.price,
sku: `${variant.sku}-copy`,
stockOnHand: 1,
featuredAssetId: variant.featuredAsset?.id,
Expand Down

0 comments on commit 18d200c

Please sign in to comment.