@vendure/core 2.2.3 → 2.2.5
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.
- package/dist/api/api-internal-modules.d.ts +2 -2
- package/dist/api/config/configure-graphql-module.js.map +1 -1
- package/dist/api/config/generate-resolvers.d.ts +4 -4
- package/dist/api/config/graphql-custom-fields.js +5 -0
- package/dist/api/config/graphql-custom-fields.js.map +1 -1
- package/dist/api/resolvers/admin/order.resolver.d.ts +1 -1
- package/dist/api/resolvers/entity/order-entity.resolver.d.ts +1 -0
- package/dist/api/resolvers/entity/order-entity.resolver.js +15 -0
- package/dist/api/resolvers/entity/order-entity.resolver.js.map +1 -1
- package/dist/bootstrap.d.ts +1 -1
- package/dist/bootstrap.js +7 -3
- package/dist/bootstrap.js.map +1 -1
- package/dist/config/config.service.d.ts +2 -0
- package/dist/config/config.service.js +30 -1
- package/dist/config/config.service.js.map +1 -1
- package/dist/config/entity/entity-duplicators/index.d.ts +4 -4
- package/dist/config/fulfillment/default-fulfillment-process.js +0 -1
- package/dist/config/fulfillment/default-fulfillment-process.js.map +1 -1
- package/dist/config/promotion/index.d.ts +53 -53
- package/dist/connection/connection.module.d.ts +1 -1
- package/dist/i18n/i18n.service.js +1 -1
- package/dist/i18n/i18n.service.js.map +1 -1
- package/dist/i18n/messages/fr.json +138 -0
- package/dist/plugin/default-search-plugin/indexer/indexer.controller.d.ts +6 -1
- package/dist/plugin/default-search-plugin/indexer/indexer.controller.js +135 -75
- package/dist/plugin/default-search-plugin/indexer/indexer.controller.js.map +1 -1
- package/dist/plugin/plugin.module.js.map +1 -1
- package/dist/service/helpers/custom-field-relation/custom-field-relation.service.js +6 -2
- package/dist/service/helpers/custom-field-relation/custom-field-relation.service.js.map +1 -1
- package/dist/service/helpers/entity-hydrator/entity-hydrator.service.d.ts +0 -7
- package/dist/service/helpers/entity-hydrator/entity-hydrator.service.js +5 -52
- package/dist/service/helpers/entity-hydrator/entity-hydrator.service.js.map +1 -1
- package/dist/service/helpers/entity-hydrator/merge-deep.d.ts +9 -0
- package/dist/service/helpers/entity-hydrator/merge-deep.js +50 -0
- package/dist/service/helpers/entity-hydrator/merge-deep.js.map +1 -0
- package/dist/service/helpers/list-query-builder/parse-filter-params.js +1 -1
- package/dist/service/helpers/list-query-builder/parse-filter-params.js.map +1 -1
- package/dist/service/helpers/order-modifier/order-modifier.d.ts +1 -1
- package/dist/service/helpers/order-modifier/order-modifier.js +7 -0
- package/dist/service/helpers/order-modifier/order-modifier.js.map +1 -1
- package/dist/service/helpers/order-splitter/order-splitter.js +3 -2
- package/dist/service/helpers/order-splitter/order-splitter.js.map +1 -1
- package/dist/service/services/order.service.js +1 -1
- package/dist/service/services/order.service.js.map +1 -1
- package/dist/service/services/shipping-method.service.js +1 -1
- package/dist/service/services/shipping-method.service.js.map +1 -1
- package/package.json +3 -3
|
@@ -3,5 +3,5 @@ import { DataSourceOptions } from 'typeorm';
|
|
|
3
3
|
export declare class ConnectionModule {
|
|
4
4
|
static forRoot(): DynamicModule;
|
|
5
5
|
static forPlugin(): DynamicModule;
|
|
6
|
-
static getTypeOrmLogger(dbConnectionOptions: DataSourceOptions):
|
|
6
|
+
static getTypeOrmLogger(dbConnectionOptions: DataSourceOptions): "debug" | "advanced-console" | "simple-console" | "file" | import("typeorm").Logger;
|
|
7
7
|
}
|
|
@@ -74,7 +74,7 @@ let I18nService = class I18nService {
|
|
|
74
74
|
.use(i18next_icu_1.default)
|
|
75
75
|
.init({
|
|
76
76
|
nsSeparator: false,
|
|
77
|
-
preload: ['en', 'de', 'ru', 'uk'],
|
|
77
|
+
preload: ['en', 'de', 'ru', 'uk', 'fr'],
|
|
78
78
|
fallbackLng: 'en',
|
|
79
79
|
detection: {
|
|
80
80
|
lookupQuerystring: 'languageCode',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.service.js","sourceRoot":"","sources":["../../src/i18n/i18n.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA0D;AAE1D,uCAAyB;AAEzB,sDAA6C;AAC7C,4EAAyC;AACzC,sFAAwD;AACxD,8DAA8B;AAC9B,gDAAwB;AAGxB,sCAAmC;AACnC,6DAAyD;AAEzD,6CAAyC;AAmBzC;;;;;;;;;GASG;AAEI,IAAM,WAAW,GAAjB,MAAM,WAAW;IACpB;;;OAGG;IACH,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAAG,CAAC;IAEpD;;OAEG;IACH,YAAY;QACR,OAAO,iBAAO;aACT,GAAG,CAAC,iCAAiB,CAAC,gBAAgB,CAAC;aACvC,GAAG,CAAC,4BAAc,CAAC;aACnB,GAAG,CAAC,qBAAG,CAAC;aACR,IAAI,CAAC;YACF,WAAW,EAAE,KAAK;YAClB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"i18n.service.js","sourceRoot":"","sources":["../../src/i18n/i18n.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA0D;AAE1D,uCAAyB;AAEzB,sDAA6C;AAC7C,4EAAyC;AACzC,sFAAwD;AACxD,8DAA8B;AAC9B,gDAAwB;AAGxB,sCAAmC;AACnC,6DAAyD;AAEzD,6CAAyC;AAmBzC;;;;;;;;;GASG;AAEI,IAAM,WAAW,GAAjB,MAAM,WAAW;IACpB;;;OAGG;IACH,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAAG,CAAC;IAEpD;;OAEG;IACH,YAAY;QACR,OAAO,iBAAO;aACT,GAAG,CAAC,iCAAiB,CAAC,gBAAgB,CAAC;aACvC,GAAG,CAAC,4BAAc,CAAC;aACnB,GAAG,CAAC,qBAAG,CAAC;aACR,IAAI,CAAC;YACF,WAAW,EAAE,KAAK;YAClB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;YACvC,WAAW,EAAE,IAAI;YACjB,SAAS,EAAE;gBACP,iBAAiB,EAAE,cAAc;aACpC;YACD,OAAO,EAAE;gBACL,QAAQ,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,uBAAuB,CAAC;gBACvD,UAAU,EAAE,CAAC;aAChB;SACJ,CAAC,CAAC;IACX,CAAC;IAED;;OAEG;IACH,MAAM;QACF,OAAO,iCAAiB,CAAC,MAAM,CAAC,iBAAO,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;;OAMG;IACH,kBAAkB,CAAC,OAAe,EAAE,QAAgB;QAChD,IAAI,CAAC;YACD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YACxD,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,eAAM,CAAC,KAAK,CAAC,iCAAiC,QAAQ,EAAE,EAAE,aAAa,CAAC,CAAC;QAC7E,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,cAAc,CAAC,OAAe,EAAE,SAA4C;QACxE,iBAAO,CAAC,iBAAiB,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7E,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,GAAgB,EAAE,KAAmB;QAChD,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QAC1C,MAAM,CAAC,GAAc,GAAG,CAAC,CAAC,CAAC;QAE3B,IAAI,CAAC,IAAI,aAAa,YAAY,sBAAS,EAAE,CAAC;YAC1C,IAAI,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC;YACxC,IAAI,CAAC;gBACD,WAAW,GAAG,CAAC,CAAC,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;YACpE,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBACd,MAAM,OAAO,GACT,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,OAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;gBACtF,WAAW,IAAI,+BAA+B,OAAO,GAAG,CAAC;YAC7D,CAAC;YACD,KAAK,CAAC,OAAO,GAAG,WAAW,CAAC;YAC5B,8EAA8E;YAC9E,wCAAwC;YACxC,OAAQ,aAAqB,CAAC,SAAS,CAAC;QAC5C,CAAC;QAED,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;;OAGG;IACH,oBAAoB,CAAC,GAAgB,EAAE,KAAyB;QAC5D,MAAM,CAAC,GAAc,GAAG,CAAC,CAAC,CAAC;QAC3B,IAAI,WAAW,GAAW,KAAK,CAAC,OAAO,CAAC;QACxC,MAAM,GAAG,GAAG,eAAe,KAAK,CAAC,OAAO,EAAE,CAAC;QAC3C,IAAI,CAAC;YACD,WAAW,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YACd,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,OAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAClG,WAAW,IAAI,+BAA+B,OAAO,GAAG,CAAC;QAC7D,CAAC;QACD,KAAK,CAAC,OAAO,GAAG,WAAW,CAAC;IAChC,CAAC;CACJ,CAAA;AA1GY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAM0B,8BAAa;GALvC,WAAW,CA0GvB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
{
|
|
2
|
+
"error": {
|
|
3
|
+
"active-user-does-not-have-sufficient-permissions": "L'utilisateur actif ne dispose pas des permissions suffisantes",
|
|
4
|
+
"available-currency-codes-must-include-default": "availableCurrencyCodes doit inclure defaultCurrencyCode ({ defaultCurrencyCode })",
|
|
5
|
+
"cannot-delete-role": "Le rôle \"{ roleCode }\" ne peut pas être supprimé",
|
|
6
|
+
"cannot-delete-sole-superadmin": "Le seul SuperAdmin ne peut pas être supprimé",
|
|
7
|
+
"cannot-locate-customer-for-user": "Impossible de localiser un Client pour l'utilisateur",
|
|
8
|
+
"cannot-modify-role": "Le rôle \"{ roleCode }\" ne peut pas être modifié",
|
|
9
|
+
"cannot-move-collection-into-self": "Impossible de déplacer une Collection dans elle-même",
|
|
10
|
+
"cannot-transition-payment-from-to": "Impossible de changer l'état du Paiement de \"{ fromState }\" à \"{ toState }\"",
|
|
11
|
+
"cannot-transition-refund-from-to": "Impossible de changer l'état du Remboursement de \"{ fromState }\" à \"{ toState }\"",
|
|
12
|
+
"cannot-transition-fulfillment-from-to": "Impossible de changer l'état de l'Exécution de \"{ fromState }\" à \"{ toState }\"",
|
|
13
|
+
"channel-not-found": "Aucun Canal avec le token \"{ token }\" n'a été trouvé",
|
|
14
|
+
"collection-id-or-slug-must-be-provided": "L'id de la Collection ou le slug doit être fourni",
|
|
15
|
+
"collection-id-slug-mismatch": "L'id et le slug fournis font référence à des Collections différentes",
|
|
16
|
+
"conditions-required-for-action": "L'action de Promotion \"{ action }\" requiert les conditions suivantes : { conditions }",
|
|
17
|
+
"configurable-argument-is-required": "L'argument \"{ name }\" est requis",
|
|
18
|
+
"country-code-not-valid": "Le code pays \"{ countryCode }\" n'a pas été reconnu",
|
|
19
|
+
"currency-not-available-in-channel": "La devise \"{ currencyCode }\" n'est pas disponible dans le Canal actuel",
|
|
20
|
+
"customer-does-not-belong-to-customer-group": "Le client n'appartient pas à ce groupe de clients",
|
|
21
|
+
"default-channel-not-found": "Canal par défaut non trouvé",
|
|
22
|
+
"entity-has-no-translation-in-language": "L'entité traduisible \"{ entityName }\" n'a pas été traduite dans la langue demandée ({ languageCode })",
|
|
23
|
+
"entity-with-id-not-found": "Aucun(e) { entityName } avec l'id \"{ id }\" n'a été trouvé(e)",
|
|
24
|
+
"items-cannot-be-removed-from-default-channel": "Les articles ne peuvent pas être retirés du Canal par défaut",
|
|
25
|
+
"facetfilterinput-invalid-input": "Un objet FacetValueFilterInput ne peut pas spécifier les champs 'and' et 'or' simultanément",
|
|
26
|
+
"field-invalid-datetime-range-max": "La valeur du champ personnalisé \"{ name }\" [{ value }] est supérieure au maximum [{ max }]",
|
|
27
|
+
"field-invalid-datetime-range-min": "La valeur du champ personnalisé \"{ name }\" [{ value }] est inférieure au minimum [{ min }]",
|
|
28
|
+
"field-invalid-non-nullable": "La valeur du champ personnalisé \"{ name }\" ne peut pas être définie à null",
|
|
29
|
+
"field-invalid-no-permission": "Vous n'avez pas les permissions nécessaires pour mettre à jour le champ \"{ name }\"",
|
|
30
|
+
"field-invalid-number-range-max": "La valeur du champ personnalisé \"{ name }\" [{ value }] dépasse le maximum [{ max }]",
|
|
31
|
+
"field-invalid-number-range-min": "La valeur du champ personnalisé \"{ name }\" [{ value }] est inférieure au minimum [{ min }]",
|
|
32
|
+
"field-invalid-readonly": "Le champ personnalisé \"{ name }\" est en lecture seule",
|
|
33
|
+
"field-invalid-string-option": "La valeur du champ personnalisé \"{ name }\" [\"{ value }\"] est invalide. Les options valides sont : [{ validOptions }]",
|
|
34
|
+
"field-invalid-string-pattern": "La valeur du champ personnalisé \"{ name }\" [\"{ value }\"] ne correspond pas au motif [{ pattern }]",
|
|
35
|
+
"forbidden": "Vous n'êtes actuellement pas autorisé à effectuer cette action",
|
|
36
|
+
"invalid-sort-field": "Le champ de tri \"{ fieldName }\" est invalide. Les champs valides sont : { validFields }",
|
|
37
|
+
"list-query-limit-exceeded": "Impossible de prendre plus de { limit } résultats dans une requête de liste",
|
|
38
|
+
"no-active-tax-zone": "La zone fiscale active n'a pas pu être déterminée. Assurez-vous qu'une zone fiscale par défaut est définie pour le canal actuel.",
|
|
39
|
+
"no-configurable-operation-def-with-code-found": "Aucun { type } avec le code \"{ code }\" n'a été trouvé",
|
|
40
|
+
"no-price-found-for-channel": "Aucune information de prix n'a été trouvée pour l'ID de la Variante de Produit \"{ variantId}\" dans le Canal \"{ channel }\".",
|
|
41
|
+
"no-search-plugin-configured": "Aucun plugin de recherche n'a été configuré",
|
|
42
|
+
"order-could-not-be-determined-or-created": "Aucune Commande active n'a pu être déterminée ni créée",
|
|
43
|
+
"order-does-not-contain-line-with-id": "Cette commande ne contient pas de Ligne de Commande avec l'id { id }",
|
|
44
|
+
"pending-identifier-missing": "L'adresse e-mail en attente de mise à jour n'a pas pu être trouvée",
|
|
45
|
+
"permission-invalid": "La permission \"{ permission }\" ne peut pas être attribuée",
|
|
46
|
+
"product-id-or-slug-must-be-provided": "L'id du Produit ou le slug doit être fourni",
|
|
47
|
+
"product-id-slug-mismatch": "L'id et le slug fournis font référence à des Produits différents",
|
|
48
|
+
"product-option-group-already-assigned": "Le groupe d'options de produit \"{ groupCode }\" est déjà attribué au produit \"{ productName }\"",
|
|
49
|
+
"product-variant-option-ids-not-compatible": "Les optionIds de la Variante de Produit doivent inclure un optionId de chaque groupe : {groupNames}",
|
|
50
|
+
"product-variant-options-combination-already-exists": "Une Variante de Produit avec les options sélectionnées existe déjà : {variantName}",
|
|
51
|
+
"promotion-channels-can-only-be-changed-from-default-channel": "Les canaux de promotion peuvent uniquement être modifiés à partir du Canal par défaut",
|
|
52
|
+
"stockonhand-cannot-be-negative": "stockOnHand ne peut pas être une valeur négative",
|
|
53
|
+
"superadmin-must-have-superadmin-role": "Il n'est pas possible de retirer le rôle de SuperAdmin au seul SuperAdmin",
|
|
54
|
+
"target-customer-not-assigned-to-order-channels": "Le Client ciblé n'est pas assigné aux mêmes Canaux que la Commande. IDs de canaux manquants : { missingChannelIds }",
|
|
55
|
+
"unauthorized": "Les informations d'identification ne correspondent pas. Veuillez vérifier et réessayer"
|
|
56
|
+
},
|
|
57
|
+
"errorResult": {
|
|
58
|
+
"ALREADY_LOGGED_IN_ERROR": "Impossible d'attribuer un Client à la Commande lorsqu'on est déjà connecté",
|
|
59
|
+
"ALREADY_REFUNDED_ERROR": "Impossible de rembourser un Article de la Commande qui a déjà été remboursé",
|
|
60
|
+
"CANCEL_ACTIVE_ORDER_ERROR": "Impossible d'annuler des Lignes de Commande d'une Commande dans l'état \"{ orderState }\"",
|
|
61
|
+
"CANCEL_PAYMENT_ERROR": "L'annulation du paiement a échoué",
|
|
62
|
+
"CHANNEL_DEFAULT_LANGUAGE_ERROR": "Impossible de rendre la langue \"{ language }\" indisponible car elle est utilisée comme langue par défaut par le canal \"{ channelCode }\"",
|
|
63
|
+
"COUPON_CODE_EXPIRED_ERROR": "Le code coupon \"{ couponCode }\" a expiré",
|
|
64
|
+
"COUPON_CODE_INVALID_ERROR": "Le code coupon \"{ couponCode }\" n'est pas valide",
|
|
65
|
+
"COUPON_CODE_LIMIT_ERROR": "Le code coupon ne peut pas être utilisé plus de {limit, plural, one {une fois} other {# fois}} par client",
|
|
66
|
+
"CREATE_FULFILLMENT_ERROR": "Une erreur s'est produite lors de la tentative de création de l'Exécution",
|
|
67
|
+
"DUPLICATE_ENTITY_ERROR": "L'entité n'a pas pu être dupliquée",
|
|
68
|
+
"EMAIL_ADDRESS_CONFLICT_ERROR": "L'adresse e-mail n'est pas disponible",
|
|
69
|
+
"EMPTY_ORDER_LINE_SELECTION_ERROR": "Au moins une Ligne de Commande doit être spécifiée",
|
|
70
|
+
"FACET_IN_USE_ERROR": "Le Facet \"{ facetCode }\" inclut des FacetValues qui sont attribués à {productCount, plural, =0 {} one {1 Produit} other {# Produits}} {variantCount, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}}",
|
|
71
|
+
"IDENTIFIER_CHANGE_TOKEN_INVALID_ERROR": "Le jeton de changement d'identifiant n'est pas reconnu",
|
|
72
|
+
"INELIGIBLE_SHIPPING_METHOD_ERROR": "Cette Commande n'est pas éligible pour la Méthode d'Expédition sélectionnée",
|
|
73
|
+
"INSUFFICIENT_STOCK_ERROR": "{quantityAvailable, plural, =0 {Aucun article n'a été} one {Seul un article a été} other {Seulement # articles ont été}} ajouté(s) à la commande en raison d'un stock insuffisant",
|
|
74
|
+
"INSUFFICIENT_STOCK_ON_HAND_ERROR": "Impossible de créer une Exécution car \"{productVariantName}\" a un stockOnHand insuffisant ({stockOnHand})",
|
|
75
|
+
"INVALID_CREDENTIALS_ERROR": "Les informations d'identification fournies sont invalides",
|
|
76
|
+
"ITEMS_ALREADY_FULFILLED_ERROR": "Un ou plusieurs Articles de la Commande font déjà partie d'une Exécution",
|
|
77
|
+
"LANGUAGE_NOT_AVAILABLE_ERROR": "La langue \"{languageCode}\" n'est pas disponible. Activez-la d'abord via les Paramètres Globaux et réessayez",
|
|
78
|
+
"MANUAL_PAYMENT_STATE_ERROR": "Un paiement manuel ne peut être ajouté que dans l'état \"ArrangingPayment\" ou \"ArrangingAdditionalPayment\"",
|
|
79
|
+
"MIME_TYPE_ERROR": "Le type MIME \"{ mimeType }\" n'est pas autorisé.",
|
|
80
|
+
"MISSING_CONDITIONS_ERROR": "Une Promotion doit avoir au moins une condition ou un code coupon défini",
|
|
81
|
+
"MISSING_PASSWORD_ERROR": "Un mot de passe doit être fourni",
|
|
82
|
+
"NEGATIVE_QUANTITY_ERROR": "La quantité pour un Article de la Commande ne peut pas être négative",
|
|
83
|
+
"NO_ACTIVE_ORDER_ERROR": "Il n'y a aucune Commande active associée à la session en cours",
|
|
84
|
+
"NOTHING_TO_REFUND_ERROR": "Rien à rembourser",
|
|
85
|
+
"NOT_VERIFIED_ERROR": "Veuillez vérifier cette adresse e-mail avant de vous connecter",
|
|
86
|
+
"ORDER_LIMIT_ERROR": "Impossible d'ajouter des articles. Une commande peut comprendre un maximum de { maxItems } articles",
|
|
87
|
+
"ORDER_MODIFICATION_ERROR": "Le contenu de la Commande peut uniquement être modifié dans l'état \"AddingItems\"",
|
|
88
|
+
"ORDER_PAYMENT_STATE_ERROR": "Un Paiement ne peut être ajouté que lorsque la Commande est dans l'état \"ArrangingPayment\"",
|
|
89
|
+
"ORDER_STATE_TRANSITION_ERROR": "Impossible de changer l'état de la Commande de \"{ fromState }\" à \"{ toState }\"",
|
|
90
|
+
"PASSWORD_ALREADY_SET_ERROR": "Un mot de passe a déjà été défini lors de l'inscription",
|
|
91
|
+
"PASSWORD_RESET_TOKEN_EXPIRED_ERROR": "Le jeton de réinitialisation du mot de passe a expiré",
|
|
92
|
+
"PASSWORD_RESET_TOKEN_INVALID_ERROR": "Le jeton de réinitialisation du mot de passe n'est pas reconnu",
|
|
93
|
+
"PASSWORD_VALIDATION_ERROR": "Le mot de passe est invalide",
|
|
94
|
+
"PAYMENT_DECLINED_ERROR": "Le paiement a été refusé",
|
|
95
|
+
"PAYMENT_FAILED_ERROR": "Le paiement a échoué",
|
|
96
|
+
"PAYMENT_ORDER_MISMATCH_ERROR": "Le Paiement et les Lignes de Commande n'appartiennent pas à la même Commande",
|
|
97
|
+
"PAYMENT_STATE_TRANSITION_ERROR": "Impossible de changer l'état du Paiement de \"{ fromState }\" à \"{ toState }\"",
|
|
98
|
+
"PRODUCT_OPTION_IN_USE_ERROR": "Impossible de retirer le groupe d'options de produit \"{ optionGroupCode }\" car il est utilisé par {productVariantCount, plural, one {une Variante de Produit} other {# Variantes de Produit}}. Utilisez l'argument `force` pour le retirer malgré tout",
|
|
99
|
+
"QUANTITY_TOO_GREAT_ERROR": "La quantité spécifiée est supérieure aux Articles de la Commande disponibles",
|
|
100
|
+
"REFUND_AMOUNT_ERROR": "Le montant spécifié dépasse le montant remboursable pour ce paiement",
|
|
101
|
+
"REFUND_ORDER_STATE_ERROR": "Impossible de rembourser une Commande dans l'état \"{ orderState }\"",
|
|
102
|
+
"SETTLE_PAYMENT_ERROR": "L'établissement du paiement a échoué",
|
|
103
|
+
"VERIFICATION_TOKEN_EXPIRED_ERROR": "Le jeton de vérification a expiré. Utilisez refreshCustomerVerification pour envoyer un nouveau jeton.",
|
|
104
|
+
"VERIFICATION_TOKEN_INVALID_ERROR": "Le jeton de vérification n'est pas reconnu"
|
|
105
|
+
},
|
|
106
|
+
"message": {
|
|
107
|
+
"asset-to-be-deleted-is-featured": "L'{assetCount, plural, one {Asset est} other {Assets sont}} présenté(s) par {products, plural, =0 {} one {1 Produit} other {# Produits}} {variants, plural, =0 {} one { 1 Variante de Produit} other { # Variantes de Produit}} {collections, plural, =0 {} one { 1 Collection} other { # Collections}}",
|
|
108
|
+
"cannot-delete-last-stock-location": "L'emplacement de stockage restant ne peut pas être supprimé",
|
|
109
|
+
"cannot-remove-tax-category-due-to-tax-rates": "Impossible de retirer la Catégorie Fiscale \"{ name }\" car elle est référencée par {count, plural, one {1 Taux Fiscal} other {# Taux Fiscaux}}",
|
|
110
|
+
"cannot-transition-order-contains-products-which-are-unavailable": "Impossible de passer à \"{ toState }\" car la Commande contient des Variantes de Produit qui ne sont plus disponibles",
|
|
111
|
+
"cannot-transition-from-arranging-additional-payment": "Impossible de passer de \"ArrangingAdditionalPayment\" à moins que le total de la Commande ne soit couvert par des Paiements",
|
|
112
|
+
"cannot-transition-order-from-to": "Impossible de changer l'état de la Commande de \"{ fromState }\" à \"{ toState }\"",
|
|
113
|
+
"cannot-transition-no-additional-payments-needed": "Impossible de passer la Commande à l'état \"ArrangingAdditionalPayment\" car aucun paiement supplémentaire n'est nécessaire",
|
|
114
|
+
"cannot-transition-to-shipping-when-order-is-empty": "Impossible de passer la Commande à l'état \"ArrangingShipping\" lorsque celle-ci est vide",
|
|
115
|
+
"cannot-transition-to-payment-due-to-insufficient-stock": "Impossible de passer la Commande à l'état \"ArrangingPayment\" en raison d'un stock insuffisant de { productVariantNames }",
|
|
116
|
+
"cannot-transition-to-payment-without-customer": "Impossible de passer la Commande à l'état \"ArrangingPayment\" sans les détails du Client",
|
|
117
|
+
"cannot-transition-to-payment-without-shipping-method": "Impossible de passer la Commande à l'état \"ArrangingPayment\" sans Méthode d'Expédition",
|
|
118
|
+
"cannot-transition-unless-all-cancelled": "Impossible de passer la Commande à l'état \"Cancelled\" à moins que tous les Articles de la Commande ne soient annulés",
|
|
119
|
+
"cannot-transition-unless-all-order-items-delivered": "Impossible de passer la Commande à l'état \"Delivered\" à moins que tous les Articles de la Commande ne soient livrés",
|
|
120
|
+
"cannot-transition-unless-some-order-items-delivered": "Impossible de passer la Commande à l'état \"PartiallyDelivered\" à moins que certains Articles de la Commande ne soient livrés",
|
|
121
|
+
"cannot-transition-unless-some-order-items-shipped": "Impossible de passer la Commande à l'état \"PartiallyShipped\" à moins que certains Articles de la Commande ne soient expédiés",
|
|
122
|
+
"cannot-transition-unless-all-order-items-shipped": "Impossible de passer la Commande à l'état \"Shipped\" à moins que tous les Articles de la Commande ne soient expédiés",
|
|
123
|
+
"cannot-transition-without-authorized-payments": "Impossible de passer la Commande à l'état \"PaymentAuthorized\" lorsque le total n'est pas couvert par des Paiements autorisés",
|
|
124
|
+
"cannot-transition-without-modification-payment": "Peut seulement passer à l'état \"ArrangingAdditionalPayment\"",
|
|
125
|
+
"cannot-transition-without-settled-payments": "Impossible de passer la Commande à l'état \"PaymentSettled\" lorsque le total n'est pas couvert par des Paiements réglés",
|
|
126
|
+
"country-used-in-addresses": "Le Pays sélectionné ne peut pas être supprimé car il est utilisé dans {count, plural, one {1 Adresse} other {# Adresses}}",
|
|
127
|
+
"entity-duplication-no-permission": "Vous n'avez pas les permissions nécessaires pour dupliquer cette entité",
|
|
128
|
+
"entity-duplication-no-strategy-found": "Aucune stratégie de duplication avec le code \"{ code }\" n'a été trouvée pour le type d'entité \"{ entityName }\"",
|
|
129
|
+
"facet-force-deleted": "Le Facet a été supprimé et ses FacetValues ont été retirés de {products, plural, =0 {} one {1 Produit} other {# Produits}}{both, select, both {, } single {} other {}}{variants, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}}",
|
|
130
|
+
"facet-used": "Le Facet \"{ facetCode }\" inclut des FacetValues qui sont attribués à {products, plural, =0 {} one {1 Produit} other {# Produits}}{both, select, both {, } single {} other {}}{variants, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}}",
|
|
131
|
+
"facet-value-force-deleted": "La FacetValue sélectionnée a été retirée de {products, plural, =0 {} one {1 Produit} other {# Produits}}{both, select, both {, } single {} other {}}{variants, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}} et supprimée",
|
|
132
|
+
"facet-value-used": "La FacetValue \"{ facetValueCode }\" est attribuée à {products, plural, =0 {} one {1 Produit} other {# Produits}}{both, select, both {, } single {} other {}}{variants, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}}",
|
|
133
|
+
"payment-method-used-in-channels": "La méthode de paiement sélectionnée est assignée aux Canaux suivants : { channelCodes }. Définissez \"force: true\" pour la supprimer de tous les Canaux.",
|
|
134
|
+
"product-option-used": "Impossible de supprimer l'option \"{code}\" car elle est utilisée par {count, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}}",
|
|
135
|
+
"zone-used-in-channels": "La Zone sélectionnée ne peut pas être supprimée car elle est utilisée comme défaut dans les Canaux suivants : { channelCodes }",
|
|
136
|
+
"zone-used-in-tax-rates": "La Zone sélectionnée ne peut pas être supprimée car elle est utilisée dans les Taux Fiscaux suivants : { taxRateNames }"
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -3,6 +3,7 @@ import { RequestContextCacheService } from '../../../cache/request-context-cache
|
|
|
3
3
|
import { ConfigService } from '../../../config/config.service';
|
|
4
4
|
import { TransactionalConnection } from '../../../connection/transactional-connection';
|
|
5
5
|
import { Job } from '../../../job-queue/job';
|
|
6
|
+
import { EntityHydrator } from '../../../service/helpers/entity-hydrator/entity-hydrator.service';
|
|
6
7
|
import { ProductPriceApplicator } from '../../../service/helpers/product-price-applicator/product-price-applicator';
|
|
7
8
|
import { ProductVariantService } from '../../../service/services/product-variant.service';
|
|
8
9
|
import { DefaultSearchPluginInitOptions, ProductChannelMessageData, ReindexMessageResponse, UpdateAssetMessageData, UpdateIndexQueueJobData, UpdateProductMessageData, UpdateVariantMessageData, UpdateVariantsByIdJobData, VariantChannelMessageData } from '../types';
|
|
@@ -12,13 +13,14 @@ export declare const variantRelations: string[];
|
|
|
12
13
|
export declare const workerLoggerCtx = "DefaultSearchPlugin Worker";
|
|
13
14
|
export declare class IndexerController {
|
|
14
15
|
private connection;
|
|
16
|
+
private entityHydrator;
|
|
15
17
|
private productPriceApplicator;
|
|
16
18
|
private configService;
|
|
17
19
|
private requestContextCache;
|
|
18
20
|
private productVariantService;
|
|
19
21
|
private options;
|
|
20
22
|
private queue;
|
|
21
|
-
constructor(connection: TransactionalConnection, productPriceApplicator: ProductPriceApplicator, configService: ConfigService, requestContextCache: RequestContextCacheService, productVariantService: ProductVariantService, options: DefaultSearchPluginInitOptions);
|
|
23
|
+
constructor(connection: TransactionalConnection, entityHydrator: EntityHydrator, productPriceApplicator: ProductPriceApplicator, configService: ConfigService, requestContextCache: RequestContextCacheService, productVariantService: ProductVariantService, options: DefaultSearchPluginInitOptions);
|
|
22
24
|
reindex(job: Job<UpdateIndexQueueJobData>): Observable<ReindexMessageResponse>;
|
|
23
25
|
updateVariantsById(job: Job<UpdateVariantsByIdJobData>): Observable<ReindexMessageResponse>;
|
|
24
26
|
updateProduct(data: UpdateProductMessageData): Promise<boolean>;
|
|
@@ -34,7 +36,10 @@ export declare class IndexerController {
|
|
|
34
36
|
private updateProductInChannel;
|
|
35
37
|
private updateVariantsInChannel;
|
|
36
38
|
private deleteProductInChannel;
|
|
39
|
+
private loadChannel;
|
|
40
|
+
private getAllChannels;
|
|
37
41
|
private getSearchIndexQueryBuilder;
|
|
42
|
+
private getProductInChannelQueryBuilder;
|
|
38
43
|
private saveVariants;
|
|
39
44
|
/**
|
|
40
45
|
* If a Product has no variants, we create a synthetic variant for the purposes
|
|
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.IndexerController = exports.workerLoggerCtx = exports.variantRelations = exports.productRelations = exports.BATCH_SIZE = void 0;
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const generated_types_1 = require("@vendure/common/lib/generated-types");
|
|
18
|
+
const shared_utils_1 = require("@vendure/common/lib/shared-utils");
|
|
18
19
|
const unique_1 = require("@vendure/common/lib/unique");
|
|
19
20
|
const typeorm_1 = require("typeorm");
|
|
20
21
|
const request_context_cache_service_1 = require("../../../cache/request-context-cache.service");
|
|
@@ -23,8 +24,10 @@ const utils_1 = require("../../../common/utils");
|
|
|
23
24
|
const config_service_1 = require("../../../config/config.service");
|
|
24
25
|
const vendure_logger_1 = require("../../../config/logger/vendure-logger");
|
|
25
26
|
const transactional_connection_1 = require("../../../connection/transactional-connection");
|
|
27
|
+
const channel_entity_1 = require("../../../entity/channel/channel.entity");
|
|
26
28
|
const product_entity_1 = require("../../../entity/product/product.entity");
|
|
27
29
|
const product_variant_entity_1 = require("../../../entity/product-variant/product-variant.entity");
|
|
30
|
+
const entity_hydrator_service_1 = require("../../../service/helpers/entity-hydrator/entity-hydrator.service");
|
|
28
31
|
const product_price_applicator_1 = require("../../../service/helpers/product-price-applicator/product-price-applicator");
|
|
29
32
|
const product_variant_service_1 = require("../../../service/services/product-variant.service");
|
|
30
33
|
const constants_1 = require("../constants");
|
|
@@ -43,8 +46,9 @@ exports.variantRelations = [
|
|
|
43
46
|
];
|
|
44
47
|
exports.workerLoggerCtx = 'DefaultSearchPlugin Worker';
|
|
45
48
|
let IndexerController = class IndexerController {
|
|
46
|
-
constructor(connection, productPriceApplicator, configService, requestContextCache, productVariantService, options) {
|
|
49
|
+
constructor(connection, entityHydrator, productPriceApplicator, configService, requestContextCache, productVariantService, options) {
|
|
47
50
|
this.connection = connection;
|
|
51
|
+
this.entityHydrator = entityHydrator;
|
|
48
52
|
this.productPriceApplicator = productPriceApplicator;
|
|
49
53
|
this.configService = configService;
|
|
50
54
|
this.requestContextCache = requestContextCache;
|
|
@@ -56,14 +60,14 @@ let IndexerController = class IndexerController {
|
|
|
56
60
|
const { ctx: rawContext } = job.data;
|
|
57
61
|
const ctx = mutable_request_context_1.MutableRequestContext.deserialize(rawContext);
|
|
58
62
|
return (0, utils_1.asyncObservable)(async (observer) => {
|
|
63
|
+
var _a;
|
|
59
64
|
const timeStart = Date.now();
|
|
60
|
-
const
|
|
65
|
+
const channel = (_a = ctx.channel) !== null && _a !== void 0 ? _a : (await this.loadChannel(ctx, ctx.channelId));
|
|
66
|
+
const qb = this.getSearchIndexQueryBuilder(ctx, channel);
|
|
61
67
|
const count = await qb.getCount();
|
|
62
68
|
vendure_logger_1.Logger.verbose(`Reindexing ${count} variants for channel ${ctx.channel.code}`, exports.workerLoggerCtx);
|
|
63
69
|
const batches = Math.ceil(count / exports.BATCH_SIZE);
|
|
64
|
-
await this.connection
|
|
65
|
-
.getRepository(ctx, search_index_item_entity_1.SearchIndexItem)
|
|
66
|
-
.delete({ languageCode: ctx.languageCode, channelId: ctx.channelId });
|
|
70
|
+
await this.connection.getRepository(ctx, search_index_item_entity_1.SearchIndexItem).delete({ channelId: ctx.channelId });
|
|
67
71
|
vendure_logger_1.Logger.verbose('Deleted existing index items', exports.workerLoggerCtx);
|
|
68
72
|
for (let i = 0; i < batches; i++) {
|
|
69
73
|
if (job.state === generated_types_1.JobState.CANCELLED) {
|
|
@@ -105,13 +109,9 @@ let IndexerController = class IndexerController {
|
|
|
105
109
|
const end = begin + exports.BATCH_SIZE;
|
|
106
110
|
vendure_logger_1.Logger.verbose(`Updating ids from index ${begin} to ${end}`);
|
|
107
111
|
const batchIds = ids.slice(begin, end);
|
|
108
|
-
const batch = await this.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
id: (0, typeorm_1.In)(batchIds),
|
|
112
|
-
deletedAt: (0, typeorm_1.IsNull)(),
|
|
113
|
-
},
|
|
114
|
-
});
|
|
112
|
+
const batch = await this.getSearchIndexQueryBuilder(ctx, ...(await this.getAllChannels(ctx)))
|
|
113
|
+
.where('variants.deletedAt IS NULL AND variants.id IN (:...ids)', { ids: batchIds })
|
|
114
|
+
.getMany();
|
|
115
115
|
await this.saveVariants(ctx, batch);
|
|
116
116
|
observer.next({
|
|
117
117
|
total: ids.length,
|
|
@@ -138,7 +138,7 @@ let IndexerController = class IndexerController {
|
|
|
138
138
|
}
|
|
139
139
|
async deleteProduct(data) {
|
|
140
140
|
const ctx = mutable_request_context_1.MutableRequestContext.deserialize(data.ctx);
|
|
141
|
-
return this.deleteProductInChannel(ctx, data.productId, ctx.
|
|
141
|
+
return this.deleteProductInChannel(ctx, data.productId, (await this.getAllChannels(ctx)).map(x => x.id));
|
|
142
142
|
}
|
|
143
143
|
async deleteVariant(data) {
|
|
144
144
|
const ctx = mutable_request_context_1.MutableRequestContext.deserialize(data.ctx);
|
|
@@ -146,12 +146,7 @@ let IndexerController = class IndexerController {
|
|
|
146
146
|
where: { id: (0, typeorm_1.In)(data.variantIds) },
|
|
147
147
|
});
|
|
148
148
|
if (variants.length) {
|
|
149
|
-
|
|
150
|
-
...variants
|
|
151
|
-
.reduce((vt, v) => [...vt, ...v.translations], [])
|
|
152
|
-
.map(t => t.languageCode),
|
|
153
|
-
]);
|
|
154
|
-
await this.removeSearchIndexItems(ctx, ctx.channelId, variants.map(v => v.id), languageVariants);
|
|
149
|
+
await this.removeSearchIndexItems(ctx, variants.map(v => v.id), (await this.getAllChannels(ctx)).map(c => c.id));
|
|
155
150
|
}
|
|
156
151
|
return true;
|
|
157
152
|
}
|
|
@@ -161,7 +156,7 @@ let IndexerController = class IndexerController {
|
|
|
161
156
|
}
|
|
162
157
|
async removeProductFromChannel(data) {
|
|
163
158
|
const ctx = mutable_request_context_1.MutableRequestContext.deserialize(data.ctx);
|
|
164
|
-
return this.deleteProductInChannel(ctx, data.productId, data.channelId);
|
|
159
|
+
return this.deleteProductInChannel(ctx, data.productId, [data.channelId]);
|
|
165
160
|
}
|
|
166
161
|
async assignVariantToChannel(data) {
|
|
167
162
|
const ctx = mutable_request_context_1.MutableRequestContext.deserialize(data.ctx);
|
|
@@ -174,7 +169,7 @@ let IndexerController = class IndexerController {
|
|
|
174
169
|
.getRepository(ctx, product_variant_entity_1.ProductVariant)
|
|
175
170
|
.findOne({ where: { id: data.productVariantId } });
|
|
176
171
|
const languageVariants = (_a = variant === null || variant === void 0 ? void 0 : variant.translations.map(t => t.languageCode)) !== null && _a !== void 0 ? _a : [];
|
|
177
|
-
await this.removeSearchIndexItems(ctx, data.
|
|
172
|
+
await this.removeSearchIndexItems(ctx, [data.productVariantId], [data.channelId]);
|
|
178
173
|
return true;
|
|
179
174
|
}
|
|
180
175
|
async updateAsset(data) {
|
|
@@ -204,19 +199,22 @@ let IndexerController = class IndexerController {
|
|
|
204
199
|
return true;
|
|
205
200
|
}
|
|
206
201
|
async updateProductInChannel(ctx, productId, channelId) {
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
});
|
|
202
|
+
const channel = await this.loadChannel(ctx, channelId);
|
|
203
|
+
ctx.setChannel(channel);
|
|
204
|
+
const product = await this.getProductInChannelQueryBuilder(ctx, productId, channel).getOneOrFail();
|
|
211
205
|
if (product) {
|
|
212
|
-
const
|
|
213
|
-
relations: exports.variantRelations,
|
|
206
|
+
const affectedChannels = await this.getAllChannels(ctx, {
|
|
214
207
|
where: {
|
|
215
|
-
|
|
216
|
-
deletedAt: (0, typeorm_1.IsNull)(),
|
|
208
|
+
availableLanguageCodes: (0, typeorm_1.In)(product.translations.map(t => t.languageCode)),
|
|
217
209
|
},
|
|
218
210
|
});
|
|
211
|
+
const updatedVariants = await this.getSearchIndexQueryBuilder(ctx, ...(0, unique_1.unique)(affectedChannels.concat(channel)))
|
|
212
|
+
.andWhere('variants.productId = :productId', { productId })
|
|
213
|
+
.getMany();
|
|
219
214
|
if (updatedVariants.length === 0) {
|
|
215
|
+
const clone = new product_entity_1.Product({ id: product.id });
|
|
216
|
+
await this.entityHydrator.hydrate(ctx, clone, { relations: ['translations'] });
|
|
217
|
+
product.translations = clone.translations;
|
|
220
218
|
await this.saveSyntheticVariant(ctx, product);
|
|
221
219
|
}
|
|
222
220
|
else {
|
|
@@ -233,89 +231,140 @@ let IndexerController = class IndexerController {
|
|
|
233
231
|
return true;
|
|
234
232
|
}
|
|
235
233
|
async updateVariantsInChannel(ctx, variantIds, channelId) {
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
},
|
|
242
|
-
});
|
|
234
|
+
const channel = await this.loadChannel(ctx, channelId);
|
|
235
|
+
ctx.setChannel(channel);
|
|
236
|
+
const variants = await this.getSearchIndexQueryBuilder(ctx, channel)
|
|
237
|
+
.andWhere('variants.deletedAt IS NULL AND variants.id IN (:...variantIds)', { variantIds })
|
|
238
|
+
.getMany();
|
|
243
239
|
if (variants) {
|
|
244
240
|
vendure_logger_1.Logger.verbose(`Updating ${variants.length} variants`, exports.workerLoggerCtx);
|
|
245
241
|
await this.saveVariants(ctx, variants);
|
|
246
242
|
}
|
|
247
243
|
return true;
|
|
248
244
|
}
|
|
249
|
-
async deleteProductInChannel(ctx, productId,
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
245
|
+
async deleteProductInChannel(ctx, productId, channelIds) {
|
|
246
|
+
const channels = await Promise.all(channelIds.map(channelId => this.loadChannel(ctx, channelId)));
|
|
247
|
+
const product = await this.getProductInChannelQueryBuilder(ctx, productId, ...channels)
|
|
248
|
+
.leftJoinAndSelect('product.variants', 'variants')
|
|
249
|
+
.leftJoinAndSelect('variants.translations', 'variants_translations')
|
|
250
|
+
.getOne();
|
|
254
251
|
if (product) {
|
|
255
|
-
const languageVariants = (0, unique_1.unique)([
|
|
256
|
-
...product.translations.map(t => t.languageCode),
|
|
257
|
-
...product.variants
|
|
258
|
-
.reduce((vt, v) => [...vt, ...v.translations], [])
|
|
259
|
-
.map(t => t.languageCode),
|
|
260
|
-
]);
|
|
261
252
|
const removedVariantIds = product.variants.map(v => v.id);
|
|
262
253
|
if (removedVariantIds.length) {
|
|
263
|
-
await this.removeSearchIndexItems(ctx,
|
|
254
|
+
await this.removeSearchIndexItems(ctx, removedVariantIds, channelIds);
|
|
264
255
|
}
|
|
265
256
|
}
|
|
266
257
|
return true;
|
|
267
258
|
}
|
|
268
|
-
|
|
259
|
+
async loadChannel(ctx, channelId) {
|
|
260
|
+
return await this.connection.getRepository(ctx, channel_entity_1.Channel).findOneOrFail({ where: { id: channelId } });
|
|
261
|
+
}
|
|
262
|
+
async getAllChannels(ctx, options) {
|
|
263
|
+
return await this.connection.getRepository(ctx, channel_entity_1.Channel).find(options);
|
|
264
|
+
}
|
|
265
|
+
getSearchIndexQueryBuilder(ctx, ...channels) {
|
|
266
|
+
const channelLanguages = (0, unique_1.unique)(channels.flatMap(c => c.availableLanguageCodes).concat(this.configService.defaultLanguageCode));
|
|
269
267
|
const qb = this.connection
|
|
270
268
|
.getRepository(ctx, product_variant_entity_1.ProductVariant)
|
|
271
269
|
.createQueryBuilder('variants')
|
|
272
270
|
.setFindOptions({
|
|
273
|
-
|
|
274
|
-
|
|
271
|
+
loadEagerRelations: false,
|
|
272
|
+
})
|
|
273
|
+
.leftJoinAndSelect('variants.channels', 'variant_channels', 'variant_channels.id IN (:...channelId)', {
|
|
274
|
+
channelId: channels.map(x => x.id),
|
|
275
|
+
})
|
|
276
|
+
.leftJoinAndSelect('variant_channels.defaultTaxZone', 'variant_channel_tax_zone')
|
|
277
|
+
.leftJoinAndSelect('variants.taxCategory', 'variant_tax_category')
|
|
278
|
+
.leftJoinAndSelect('variants.productVariantPrices', 'product_variant_prices', 'product_variant_prices.channelId IN (:...channelId)', { channelId: channels.map(x => x.id) })
|
|
279
|
+
.leftJoinAndSelect('variants.translations', 'product_variant_translation', 'product_variant_translation.baseId = variants.id AND product_variant_translation.languageCode IN (:...channelLanguages)', {
|
|
280
|
+
channelLanguages,
|
|
275
281
|
})
|
|
276
282
|
.leftJoin('variants.product', 'product')
|
|
283
|
+
.leftJoinAndSelect('variants.facetValues', 'variant_facet_values')
|
|
284
|
+
.leftJoinAndSelect('variant_facet_values.translations', 'variant_facet_value_translations', 'variant_facet_value_translations.languageCode IN (:...channelLanguages)', {
|
|
285
|
+
channelLanguages,
|
|
286
|
+
})
|
|
287
|
+
.leftJoinAndSelect('variant_facet_values.facet', 'facet_values_facet')
|
|
288
|
+
.leftJoinAndSelect('facet_values_facet.translations', 'facet_values_facet_translations', 'facet_values_facet_translations.languageCode IN (:...channelLanguages)', {
|
|
289
|
+
channelLanguages,
|
|
290
|
+
})
|
|
291
|
+
.leftJoinAndSelect('variants.collections', 'collections')
|
|
292
|
+
.leftJoinAndSelect('collections.channels', 'collection_channels', 'collection_channels.id IN (:...channelId)', { channelId: channels.map(x => x.id) })
|
|
293
|
+
.leftJoinAndSelect('collections.translations', 'collection_translations', 'collection_translations.languageCode IN (:...channelLanguages)', {
|
|
294
|
+
channelLanguages,
|
|
295
|
+
})
|
|
277
296
|
.leftJoin('product.channels', 'channel')
|
|
278
|
-
.where('channel.id
|
|
297
|
+
.where('channel.id IN (:...channelId)', { channelId: channels.map(x => x.id) })
|
|
279
298
|
.andWhere('product.deletedAt IS NULL')
|
|
280
299
|
.andWhere('variants.deletedAt IS NULL');
|
|
281
300
|
return qb;
|
|
282
301
|
}
|
|
302
|
+
getProductInChannelQueryBuilder(ctx, productId, ...channels) {
|
|
303
|
+
const channelLanguages = (0, unique_1.unique)(channels.flatMap(c => c.availableLanguageCodes).concat(this.configService.defaultLanguageCode));
|
|
304
|
+
return this.connection
|
|
305
|
+
.getRepository(ctx, product_entity_1.Product)
|
|
306
|
+
.createQueryBuilder('product')
|
|
307
|
+
.setFindOptions({
|
|
308
|
+
loadEagerRelations: false,
|
|
309
|
+
})
|
|
310
|
+
.leftJoinAndSelect('product.translations', 'translations', 'translations.languageCode IN (:...channelLanguages)', {
|
|
311
|
+
channelLanguages,
|
|
312
|
+
})
|
|
313
|
+
.leftJoinAndSelect('product.featuredAsset', 'product_featured_asset')
|
|
314
|
+
.leftJoinAndSelect('product.facetValues', 'product_facet_values')
|
|
315
|
+
.leftJoinAndSelect('product_facet_values.translations', 'product_facet_value_translations', 'product_facet_value_translations.languageCode IN (:...channelLanguages)', {
|
|
316
|
+
channelLanguages,
|
|
317
|
+
})
|
|
318
|
+
.leftJoinAndSelect('product_facet_values.facet', 'product_facet')
|
|
319
|
+
.leftJoinAndSelect('product_facet.translations', 'product_facet_translations', 'product_facet_translations.languageCode IN (:...channelLanguages)', {
|
|
320
|
+
channelLanguages,
|
|
321
|
+
})
|
|
322
|
+
.leftJoinAndSelect('product.channels', 'channel', 'channel.id IN (:...channelId)', {
|
|
323
|
+
channelId: channels.map(x => x.id),
|
|
324
|
+
})
|
|
325
|
+
.where('product.id = :productId', { productId });
|
|
326
|
+
}
|
|
283
327
|
async saveVariants(ctx, variants) {
|
|
328
|
+
var _a, _b, _c, _d, _e;
|
|
284
329
|
const items = [];
|
|
285
330
|
await this.removeSyntheticVariants(ctx, variants);
|
|
286
331
|
const productMap = new Map();
|
|
287
332
|
for (const variant of variants) {
|
|
288
333
|
let product = productMap.get(variant.productId);
|
|
289
334
|
if (!product) {
|
|
290
|
-
product = await this.
|
|
291
|
-
relations: exports.productRelations,
|
|
292
|
-
});
|
|
335
|
+
product = await this.getProductInChannelQueryBuilder(ctx, variant.productId, ctx.channel).getOneOrFail();
|
|
293
336
|
productMap.set(variant.productId, product);
|
|
294
337
|
}
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
...product.translations.map(t => t.languageCode),
|
|
298
|
-
]);
|
|
299
|
-
for (const languageCode of languageVariants) {
|
|
338
|
+
const availableLanguageCodes = (0, unique_1.unique)(ctx.channel.availableLanguageCodes);
|
|
339
|
+
for (const languageCode of availableLanguageCodes) {
|
|
300
340
|
const productTranslation = this.getTranslation(product, languageCode);
|
|
301
341
|
const variantTranslation = this.getTranslation(variant, languageCode);
|
|
302
342
|
const collectionTranslations = variant.collections.map(c => this.getTranslation(c, languageCode));
|
|
343
|
+
let channelIds = variant.channels.map(x => x.id);
|
|
344
|
+
const clone = new product_variant_entity_1.ProductVariant({ id: variant.id });
|
|
345
|
+
await this.entityHydrator.hydrate(ctx, clone, {
|
|
346
|
+
relations: ['channels', 'channels.defaultTaxZone'],
|
|
347
|
+
});
|
|
348
|
+
channelIds.push(...clone.channels
|
|
349
|
+
.filter(x => x.availableLanguageCodes.includes(languageCode))
|
|
350
|
+
.map(x => x.id));
|
|
351
|
+
channelIds = (0, unique_1.unique)(channelIds);
|
|
303
352
|
for (const channel of variant.channels) {
|
|
304
353
|
ctx.setChannel(channel);
|
|
305
354
|
await this.productPriceApplicator.applyChannelPriceAndTax(variant, ctx);
|
|
306
355
|
const item = new search_index_item_entity_1.SearchIndexItem({
|
|
307
|
-
channelId:
|
|
356
|
+
channelId: ctx.channelId,
|
|
308
357
|
languageCode,
|
|
309
358
|
productVariantId: variant.id,
|
|
310
359
|
price: variant.price,
|
|
311
360
|
priceWithTax: variant.priceWithTax,
|
|
312
361
|
sku: variant.sku,
|
|
313
362
|
enabled: product.enabled === false ? false : variant.enabled,
|
|
314
|
-
slug: productTranslation.slug,
|
|
363
|
+
slug: (_a = productTranslation === null || productTranslation === void 0 ? void 0 : productTranslation.slug) !== null && _a !== void 0 ? _a : '',
|
|
315
364
|
productId: product.id,
|
|
316
|
-
productName: productTranslation.name,
|
|
317
|
-
description: this.constrainDescription(productTranslation.description),
|
|
318
|
-
productVariantName: variantTranslation.name,
|
|
365
|
+
productName: (_b = productTranslation === null || productTranslation === void 0 ? void 0 : productTranslation.name) !== null && _b !== void 0 ? _b : '',
|
|
366
|
+
description: this.constrainDescription((_c = productTranslation === null || productTranslation === void 0 ? void 0 : productTranslation.description) !== null && _c !== void 0 ? _c : ''),
|
|
367
|
+
productVariantName: (_d = variantTranslation === null || variantTranslation === void 0 ? void 0 : variantTranslation.name) !== null && _d !== void 0 ? _d : '',
|
|
319
368
|
productAssetId: product.featuredAsset ? product.featuredAsset.id : null,
|
|
320
369
|
productPreviewFocalPoint: product.featuredAsset
|
|
321
370
|
? product.featuredAsset.focalPoint
|
|
@@ -326,11 +375,11 @@ let IndexerController = class IndexerController {
|
|
|
326
375
|
productVariantAssetId: variant.featuredAsset ? variant.featuredAsset.id : null,
|
|
327
376
|
productPreview: product.featuredAsset ? product.featuredAsset.preview : '',
|
|
328
377
|
productVariantPreview: variant.featuredAsset ? variant.featuredAsset.preview : '',
|
|
329
|
-
channelIds:
|
|
378
|
+
channelIds: channelIds.map(x => x.toString()),
|
|
330
379
|
facetIds: this.getFacetIds(variant, product),
|
|
331
380
|
facetValueIds: this.getFacetValueIds(variant, product),
|
|
332
381
|
collectionIds: variant.collections.map(c => c.id.toString()),
|
|
333
|
-
collectionSlugs: collectionTranslations.map(c => c.slug),
|
|
382
|
+
collectionSlugs: (_e = collectionTranslations.map(c => c === null || c === void 0 ? void 0 : c.slug).filter(shared_utils_1.notNullOrUndefined)) !== null && _e !== void 0 ? _e : [],
|
|
334
383
|
});
|
|
335
384
|
if (this.options.indexStockStatus) {
|
|
336
385
|
item.inStock =
|
|
@@ -420,15 +469,25 @@ let IndexerController = class IndexerController {
|
|
|
420
469
|
/**
|
|
421
470
|
* Remove items from the search index
|
|
422
471
|
*/
|
|
423
|
-
async removeSearchIndexItems(ctx,
|
|
472
|
+
async removeSearchIndexItems(ctx, variantIds, channelIds, ...languageCodes) {
|
|
424
473
|
const keys = [];
|
|
425
474
|
for (const productVariantId of variantIds) {
|
|
426
|
-
for (const
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
475
|
+
for (const channelId of channelIds) {
|
|
476
|
+
if (languageCodes.length > 0) {
|
|
477
|
+
for (const languageCode of languageCodes) {
|
|
478
|
+
keys.push({
|
|
479
|
+
productVariantId,
|
|
480
|
+
channelId,
|
|
481
|
+
languageCode,
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
keys.push({
|
|
487
|
+
productVariantId,
|
|
488
|
+
channelId,
|
|
489
|
+
});
|
|
490
|
+
}
|
|
432
491
|
}
|
|
433
492
|
}
|
|
434
493
|
await this.queue.push(() => this.connection.getRepository(ctx, search_index_item_entity_1.SearchIndexItem).delete(keys));
|
|
@@ -449,8 +508,9 @@ let IndexerController = class IndexerController {
|
|
|
449
508
|
exports.IndexerController = IndexerController;
|
|
450
509
|
exports.IndexerController = IndexerController = __decorate([
|
|
451
510
|
(0, common_1.Injectable)(),
|
|
452
|
-
__param(
|
|
511
|
+
__param(6, (0, common_1.Inject)(constants_1.PLUGIN_INIT_OPTIONS)),
|
|
453
512
|
__metadata("design:paramtypes", [transactional_connection_1.TransactionalConnection,
|
|
513
|
+
entity_hydrator_service_1.EntityHydrator,
|
|
454
514
|
product_price_applicator_1.ProductPriceApplicator,
|
|
455
515
|
config_service_1.ConfigService,
|
|
456
516
|
request_context_cache_service_1.RequestContextCacheService,
|