@haus-tech/product-import-export-plugin 2.2.0-dev.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,12 +45,16 @@ let ExtendedAssetImporter = class ExtendedAssetImporter {
45
45
  for (const assetPath of uniqueAssetPaths.values()) {
46
46
  const cachedAsset = this.assetMap.get(assetPath.url);
47
47
  if (cachedAsset) {
48
- if (assetPath.id && cachedAsset.name !== assetPath.name) {
48
+ if (cachedAsset.name !== assetPath.name && assetPath.name) {
49
49
  this.connection.getRepository(ctx, core_1.Asset).update(cachedAsset.id, {
50
50
  name: assetPath.name,
51
51
  });
52
+ this.assetMap.set(assetPath.url, { ...cachedAsset, name: assetPath.name });
53
+ assets.push({ ...cachedAsset, name: assetPath.name });
54
+ }
55
+ else {
56
+ assets.push(cachedAsset);
52
57
  }
53
- assets.push(cachedAsset);
54
58
  }
55
59
  else {
56
60
  try {
@@ -65,6 +69,12 @@ let ExtendedAssetImporter = class ExtendedAssetImporter {
65
69
  },
66
70
  });
67
71
  if (assetFromHash) {
72
+ // Check if the asset name has changed
73
+ if (assetPath.name && assetFromHash.name !== assetPath.name) {
74
+ await this.connection.getRepository(ctx, core_1.Asset).update(assetFromHash.id, {
75
+ name: assetPath.name,
76
+ });
77
+ }
68
78
  this.assetMap.set(assetPath.url, assetFromHash);
69
79
  assets.push(assetFromHash);
70
80
  continue;
@@ -89,6 +99,7 @@ let ExtendedAssetImporter = class ExtendedAssetImporter {
89
99
  shouldDeleteCreatedAsset = true;
90
100
  assetToUpdate = { ...assetFromHash, name: assetPath.name || assetFromHash.name };
91
101
  }
102
+ console.log('assetFromHash', assetFromHash);
92
103
  if (assetPath.id) {
93
104
  shouldDeleteCreatedAsset = true;
94
105
  assetToUpdate = {
@@ -294,6 +294,7 @@ let ProductImporter = class ProductImporter {
294
294
  'variants',
295
295
  'variants.facetValues',
296
296
  'assets',
297
+ 'featuredAsset',
297
298
  ],
298
299
  })
299
300
  : undefined;
@@ -322,10 +323,17 @@ let ProductImporter = class ProductImporter {
322
323
  previousNormalizedName: (0, normalize_string_1.normalizeString)(existingProductName),
323
324
  }
324
325
  : undefined;
326
+ if (existingProduct && updatingStrategy === 'replace') {
327
+ await this.fastImporter.removeAllAssetsFromProduct(existingProduct);
328
+ }
325
329
  const productData = {
326
- featuredAssetId: productAssets.length ? productAssets[0].id : undefined,
330
+ featuredAssetId: existingProduct?.featuredAsset
331
+ ? undefined
332
+ : productAssets.length
333
+ ? productAssets[0].id
334
+ : undefined,
327
335
  assetIds: productAssets.map((a) => a.id),
328
- // facetValueIds: await this.getFacetValueIds(ctx, product.facets, ctx.languageCode),
336
+ facetValueIds: updatingStrategy === 'replace' ? [] : undefined,
329
337
  translations: await Promise.all(product.translations.map(async (translation) => {
330
338
  return {
331
339
  languageCode: translation.languageCode,
@@ -430,6 +438,7 @@ let ProductImporter = class ProductImporter {
430
438
  sku: variant.sku,
431
439
  },
432
440
  withDeleted: true,
441
+ relations: ['facetValues', 'facetValues.facet', 'assets', 'featuredAsset'],
433
442
  });
434
443
  if (existingVariant?.deletedAt) {
435
444
  existingVariant.deletedAt = null;
@@ -441,10 +450,18 @@ let ProductImporter = class ProductImporter {
441
450
  console.error('Error while restoring the variant:', error);
442
451
  }
443
452
  }
453
+ if (existingVariant && updatingStrategy === 'replace') {
454
+ // Remove all assets from the product
455
+ await this.fastImporter.removeAllAssetsFromVariant(existingVariant);
456
+ }
444
457
  const variantData = {
445
458
  productId: createdProductId,
446
- // facetValueIds,
447
- featuredAssetId: variantAssets.length ? variantAssets[0].id : undefined,
459
+ facetValueIds: updatingStrategy === 'replace' ? [] : undefined,
460
+ featuredAssetId: existingVariant?.featuredAsset
461
+ ? undefined
462
+ : variantAssets.length
463
+ ? variantAssets[0].id
464
+ : undefined,
448
465
  assetIds: variantAssets.map((a) => a.id),
449
466
  sku: variant.sku,
450
467
  taxCategoryId: this.getMatchingTaxCategoryId(variant.taxCategory, taxCategories.items),
@@ -1,4 +1,4 @@
1
- import { Channel, ChannelService, EntityHydrator, ID, RequestContextService, StockMovementService, TransactionalConnection, TranslatableSaver } from '@vendure/core';
1
+ import { Channel, ChannelService, EntityHydrator, ID, Product, ProductVariant, RequestContextService, StockMovementService, TransactionalConnection, TranslatableSaver } from '@vendure/core';
2
2
  import { CreateFacetInput, CreateFacetValueInput, CreateProductInput, CreateProductOptionGroupInput, CreateProductOptionInput, CreateProductVariantInput } from '@vendure/common/lib/generated-types';
3
3
  export declare class ExtendedFastImporterService {
4
4
  private connection;
@@ -23,6 +23,8 @@ export declare class ExtendedFastImporterService {
23
23
  updateProduct(id: ID, input: CreateProductInput & {
24
24
  id: ID;
25
25
  }): Promise<ID>;
26
+ removeAllAssetsFromProduct(product: Product): Promise<void>;
27
+ removeAllAssetsFromVariant(variant: ProductVariant): Promise<void>;
26
28
  createProduct(input: CreateProductInput): Promise<ID>;
27
29
  updateProductOptionGroup(input: CreateProductOptionGroupInput & {
28
30
  id: ID;
@@ -63,6 +63,9 @@ let ExtendedFastImporterService = class ExtendedFastImporterService {
63
63
  beforeSave: async (p) => {
64
64
  await this.entityHydrator.hydrate(this.importCtx, p, { relations: ['channels'] });
65
65
  p.channels = (0, unique_1.unique)([...p.channels, this.defaultChannel, this.importCtx.channel], 'id');
66
+ if (input.facetValueIds) {
67
+ p.facetValues = input.facetValueIds.map((id) => ({ id }));
68
+ }
66
69
  if (input.featuredAssetId) {
67
70
  p.featuredAsset = { id: input.featuredAssetId };
68
71
  }
@@ -83,6 +86,20 @@ let ExtendedFastImporterService = class ExtendedFastImporterService {
83
86
  }
84
87
  return product.id;
85
88
  }
89
+ async removeAllAssetsFromProduct(product) {
90
+ this.ensureInitialized();
91
+ await this.connection
92
+ .getRepository(this.importCtx, core_1.ProductAsset)
93
+ .delete({ productId: product.id });
94
+ product.featuredAsset = undefined;
95
+ }
96
+ async removeAllAssetsFromVariant(variant) {
97
+ this.ensureInitialized();
98
+ await this.connection
99
+ .getRepository(this.importCtx, core_1.ProductVariantAsset)
100
+ .delete({ productVariantId: variant.id });
101
+ variant.featuredAsset = undefined;
102
+ }
86
103
  async createProduct(input) {
87
104
  this.ensureInitialized();
88
105
  // https://github.com/vendure-ecommerce/vendure/issues/2053
@@ -310,6 +327,9 @@ let ExtendedFastImporterService = class ExtendedFastImporterService {
310
327
  if (optionIds && optionIds.length) {
311
328
  variant.options = optionIds.map((id) => ({ id }));
312
329
  }
330
+ if (input.facetValueIds) {
331
+ variant.facetValues = input.facetValueIds.map((id) => ({ id }));
332
+ }
313
333
  variant.product = { id: input.productId };
314
334
  variant.taxCategory = { id: input.taxCategoryId };
315
335
  if (input.featuredAssetId) {
package/dist/types.d.ts CHANGED
@@ -37,5 +37,5 @@ export type JsonAsset = {
37
37
  type ExportFields = Array<ProductFields | VariantFields>;
38
38
  type ProductFields = 'productId' | 'name' | 'slug' | 'description' | 'assets' | 'facets' | 'optionGroups';
39
39
  type VariantFields = 'sku' | 'optionValues' | 'price' | 'taxCategory' | 'stockOnHand' | 'trackInventory' | 'variantAssets' | 'variantFacets';
40
- export type UpdatingStrategy = 'overwrite' | 'merge';
40
+ export type UpdatingStrategy = 'replace' | 'merge';
41
41
  export {};
@@ -3,7 +3,7 @@ import { NotificationService, LocalStorageService } from '@vendure/admin-ui/core
3
3
  import { TranslateService } from '@ngx-translate/core';
4
4
  import { AdminUiConfig } from '@vendure/common/lib/shared-types';
5
5
  import { Channel, LanguageCode } from '@vendure/core';
6
- type UpdatingStrategy = 'overwrite' | 'merge';
6
+ type UpdatingStrategy = 'replace' | 'merge';
7
7
  type ImportOptions = {
8
8
  updateProductSlug?: string;
9
9
  };
@@ -83,11 +83,11 @@
83
83
  <input
84
84
  type="radio"
85
85
  name="updatingStrategy"
86
- value="overwrite"
86
+ value="merge"
87
87
  [(ngModel)]="updatingStrategy"
88
88
  style="width: fit-content"
89
89
  />
90
- {{ 'product-import.card.overwrite' | translate }}
90
+ {{ 'product-import.card.merge' | translate }}
91
91
  </label>
92
92
  </div>
93
93
  <div>
@@ -95,11 +95,14 @@
95
95
  <input
96
96
  type="radio"
97
97
  name="updatingStrategy"
98
- value="merge"
98
+ value="replace"
99
99
  [(ngModel)]="updatingStrategy"
100
100
  style="width: fit-content"
101
101
  />
102
- {{ 'product-import.card.merge' | translate }}
102
+ {{ 'product-import.card.overwrite' | translate }}<br />
103
+ <span *ngIf="updatingStrategy === 'replace'" style="color: red; font-size: 12px">{{
104
+ 'product-import.card.overwrite-warning' | translate
105
+ }}</span>
103
106
  </label>
104
107
  </div>
105
108
  </div>
@@ -91,6 +91,7 @@ let ProductImportComponent = class ProductImportComponent {
91
91
  this.selectedFile = null;
92
92
  this.validateFile = null;
93
93
  this.selectedMainLanguage = undefined;
94
+ this.updatingStrategy = 'merge';
94
95
  }
95
96
  async validateCsvStructure(file) {
96
97
  const baseColumns = ['sku'];
@@ -7,7 +7,7 @@ import { endsWith, startsWith, size, uniq } from 'lodash'
7
7
  import { AdminUiConfig } from '@vendure/common/lib/shared-types'
8
8
  import { Channel, LanguageCode } from '@vendure/core'
9
9
 
10
- type UpdatingStrategy = 'overwrite' | 'merge'
10
+ type UpdatingStrategy = 'replace' | 'merge'
11
11
 
12
12
  type ImportOptions = {
13
13
  updateProductSlug?: string
@@ -117,6 +117,7 @@ export class ProductImportComponent implements OnInit {
117
117
  this.selectedFile = null
118
118
  this.validateFile = null
119
119
  this.selectedMainLanguage = undefined
120
+ this.updatingStrategy = 'merge'
120
121
  }
121
122
 
122
123
  async validateCsvStructure(file: File): Promise<ValidateReturnType> {
@@ -10,6 +10,7 @@
10
10
  "select-main-language": "Select main language: ",
11
11
  "updating-strategy": "Updating strategy for facets and assets: ",
12
12
  "overwrite": "Overwrite",
13
+ "overwrite-warning": "Warning: This will remove existing facets and assets from products and variants.",
13
14
  "merge": "Merge",
14
15
  "main-language-info": "The main language is used as a fallback when translations are missing. It is recommended to select the language that is used the most in your system. The main language will be used to create products, the other languages will be used to fill in translations."
15
16
  },
@@ -10,6 +10,7 @@
10
10
  "select-main-language": "Välj huvudspråk: ",
11
11
  "updating-strategy": "Uppdateringsstrategi för etiketter och filer: ",
12
12
  "overwrite": "Skriv över",
13
+ "overwrite-warning": "Varning: Detta kommer ta bort befintliga etiketter och filer från produkter och varianter.",
13
14
  "merge": "Sammanfoga",
14
15
  "main-language-info": "Huvudspråket används som fallback när översättningar saknas. Det rekommenderas att välja det språk som används mest i din kanal. Huvudspråket kommer användas för att skapa upp produkter, de övriga språken kommer användas för att fylla i översättningar."
15
16
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haus-tech/product-import-export-plugin",
3
- "version": "2.2.0-dev.1",
3
+ "version": "2.2.0",
4
4
  "description": "A Vendure plugin for importing and exporting products using a CSV file",
5
5
  "author": "Haus Tech",
6
6
  "repository": {